package org.eclipse.ui.views.pdf;
import java.text.MessageFormat;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.ControlContribution;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.views.file.ToolbarSubmenuAction;
public class PdfViewToolbarManager {
private static final String COMMAND_ID_PREFIX="org.eclipse.ui.views.pdf.";
private PdfViewPage page;
public void setPage(PdfViewPage page) {
this.page = page;
}
public PdfViewPage getPage() {
return page;
}
private final FitToAction fitToPageAction = new FitToAction("Page", "Page", true, true); //$NON-NLS-2$
private final FitToAction fitToWidthAction = new FitToAction("Width", "Width", true, false); //$NON-NLS-2$
private final FitToAction fitToHeightAction = new FitToAction("Height", "Height", false, true); //$NON-NLS-2$
private final IContributionItem[] contributions = new IContributionItem[] {
new ActionContributionItem(new FirstPageAction()),
new ActionContributionItem(new PreviousPageAction()),
new CurrentPageContribution(), new PageCountContribution(),
new ActionContributionItem(new NextPageAction()),
new ActionContributionItem(new LastPageAction()), new Separator(),
getZoomMenu()
};
public IContributionItem[] getToolbarContributions() {
return contributions;
}
public void refresh() {
for (IContributionItem contribution : contributions) {
contribution.update();
}
}
private static final String ICON_PATH = "icons/"; //$NON-NLS-1$
private static final String ID_PREFIX = ".toolbars."; //$NON-NLS-1$
// Navigation
public abstract class NavigateAction extends Action {
public NavigateAction(String tooltipTextFragment, String iconNameFragment) {
setToolTipText(MessageFormat.format("Go To {0} Page", tooltipTextFragment));
setImageDescriptor(Activator.getImageDescriptor(ICON_PATH + MessageFormat.format("{0}Page.png", iconNameFragment))); //$NON-NLS-1$
setActionDefinitionId(COMMAND_ID_PREFIX+"Navigate"+iconNameFragment);
}
@Override
public void run() {
getPage().setPage(getNewPage());
}
protected abstract int getNewPage();
@Override
public boolean isEnabled() {
int newPage=getNewPage();
return getPage()!=null && getPage().isPageValid(newPage) && getPage().getPage()!=newPage;
}
}
public class FirstPageAction extends NavigateAction {
public FirstPageAction() {
super("First", "First"); //$NON-NLS-2$
}
@Override
protected int getNewPage() {
return 1;
}
}
public class PreviousPageAction extends NavigateAction {
public PreviousPageAction() {
super("Previous", "Previous"); //$NON-NLS-2$
}
@Override
protected int getNewPage() {
return getPage().getPage() - 1;
}
}
public class NextPageAction extends NavigateAction {
public NextPageAction() {
super("Next", "Next"); //$NON-NLS-2$
}
@Override
protected int getNewPage() {
return getPage().getPage() + 1;
}
}
public class LastPageAction extends NavigateAction {
public LastPageAction() {
super("Last", "Last"); //$NON-NLS-2$
}
@Override
protected int getNewPage() {
return getPage().getPageCount();
}
}
public class CurrentPageContribution extends ControlContribution {
private Text text;
public CurrentPageContribution() {
super(Activator.getId() + ID_PREFIX + "currentPage"); //$NON-NLS-1$
}
@Override
protected int computeWidth(Control control) {
return control.computeSize(20, SWT.DEFAULT).x;
}
@Override
protected Control createControl(Composite parent) {
text = new Text(parent, SWT.SINGLE | SWT.BORDER);
text.setToolTipText("Current page");
text.addVerifyListener(new VerifyListener() {
@Override
public void verifyText(VerifyEvent event) {
for (int i = 0; i < event.text.length(); i++) {
if (!Character.isDigit(event.text.charAt(i))) {
event.doit = false;
return;
}
}
}
});
text.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent event) {
if(getPage()==null){
return;
}
if ((event.keyCode == SWT.CR || event.keyCode==SWT.KEYPAD_CR) && (text.getText().length() > 0)) {
getPage().setPage(Integer.parseInt(text.getText()));
}
}
});
text.addMouseListener(new MouseAdapter() {
@Override
public void mouseDown(MouseEvent e) {
text.setFocus();
}
});
update();
return text;
}
@Override
public void update() {
if ((text != null) && !text.isDisposed()) {
text.setText(String.valueOf(getPage().getPage()));
}
}
}
public class PageCountContribution extends ControlContribution {
private Label label;
public PageCountContribution() {
super(Activator.getId() + ID_PREFIX + "pageCount"); //$NON-NLS-1$
}
@Override
protected Control createControl(Composite parent) {
Composite container = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.marginHeight = 0;
layout.marginWidth = 1;
container.setLayout(layout);
label = new Label(container, SWT.CENTER);
GridData layoutData = new GridData();
layoutData.verticalAlignment = SWT.CENTER;
layoutData.grabExcessVerticalSpace = true;
//TODO remove hint once resizing the label works
layoutData.widthHint=22;
layoutData.horizontalAlignment=SWT.CENTER;
label.setLayoutData(layoutData);
update();
return container;
}
@Override
public void update() {
if ((label != null) && !label.isDisposed()) {
label.setText(MessageFormat.format("/{0}", getPage().getPageCount()));
label.setToolTipText("Page count");
}
}
}
// Zoom
protected static final float ZOOM_STEP = 0.25f;
public abstract class ZoomAction extends Action {
public ZoomAction(String tooltipTextFragment, String iconNameFragment) {
setToolTipText(MessageFormat.format("Zoom {0}", tooltipTextFragment));
setText(getToolTipText());
setImageDescriptor(Activator.getImageDescriptor(ICON_PATH + MessageFormat.format("Zoom{0}.png", iconNameFragment))); //$NON-NLS-1$
}
@Override
public void run() {
disableFit();
getPage().setZoom(getNewZoom());
}
protected abstract float getNewZoom();
@Override
public boolean isEnabled() {
return getPage()!=null && getPage().isZoomValid(getNewZoom());
}
}
public class ZoomOutAction extends ZoomAction {
public ZoomOutAction() {
super("Out", "Out"); //$NON-NLS-2$
setActionDefinitionId(COMMAND_ID_PREFIX+"ZoomOut");
}
@Override
protected float getNewZoom() {
return getPage().getZoom() * (1 - ZOOM_STEP);
}
}
public class ZoomInAction extends ZoomAction {
public ZoomInAction() {
super("In", "In"); //$NON-NLS-2$
setActionDefinitionId(COMMAND_ID_PREFIX+"ZoomIn");
}
@Override
protected float getNewZoom() {
return getPage().getZoom() * (1 + ZOOM_STEP);
}
}
public class ZoomToActualSizeAction extends ZoomAction {
public ZoomToActualSizeAction() {
super("To Actual Size", "ToActualSize"); //$NON-NLS-2$
setActionDefinitionId(COMMAND_ID_PREFIX+"ZoomNormal");
}
@Override
protected float getNewZoom() {
return 1;
}
}
// Zoom to fit
public void disableFit() {
fitToPageAction.setChecked(false);
fitToWidthAction.setChecked(false);
fitToHeightAction.setChecked(false);
}
public class FitToAction extends Action {
private final ControlListener resizeListener = new ControlAdapter() {
private AtomicBoolean preventZoomingToOftenLock=new AtomicBoolean(false);
@Override
public void controlResized(ControlEvent e) {
if(preventZoomingToOftenLock.get()){
//workaround for for problem described in pull request 17
return;
}
preventZoomingToOftenLock.set(true);
PdfViewPage page = getPage();
float widthRatio = Float.MAX_VALUE;
if (fitToWidth) {
float imageWidth = page.getClientArea().width - page.getVerticalBar().getSize().x;
int pageWidth = page.getPageWidth();
widthRatio = imageWidth / pageWidth;
}
float heightRatio = Float.MAX_VALUE;
if (fitToHeight) {
float imageHeight = page.getClientArea().height - page.getHorizontalBar().getSize().y;
int pageHeight = page.getPageHeight();
heightRatio = imageHeight / pageHeight;
}
page.setZoom(Math.min(widthRatio, heightRatio));
preventZoomingToOftenLock.set(false);
}
};
private final boolean fitToWidth;
private final boolean fitToHeight;
public FitToAction(String tooltipTextFragment, String iconNameFragment, boolean fitToWidth, boolean fitToHeight) {
super(null, AS_RADIO_BUTTON);
if (!fitToWidth && !fitToHeight) {
throw new IllegalArgumentException("At least one dimension must be specified"); //$NON-NLS-1$
}
this.fitToWidth = fitToWidth;
this.fitToHeight = fitToHeight;
setToolTipText(MessageFormat.format("Fit To {0}", tooltipTextFragment));
setText(getToolTipText());
setImageDescriptor(Activator.getImageDescriptor(ICON_PATH + MessageFormat.format("FitTo{0}.png", iconNameFragment))); //$NON-NLS-1$
setActionDefinitionId(COMMAND_ID_PREFIX+"Zoom"+iconNameFragment);
}
@Override
public void setChecked(boolean checked) {
if(checked){
//ensure disabling other radio buttons when using short cuts
disableFit();
}
if (checked != isChecked()) {
super.setChecked(checked);
PdfViewPage page = getPage();
if (checked) {
resizeListener.controlResized(null);
page.addControlListener(resizeListener);
page.setFitToAction(this); // Save special zoom setting
} else {
page.removeControlListener(resizeListener);
if (page.getFitToAction() == this) { // Clear special zoom setting
page.setFitToAction(null);
}
}
}
}
@Override
public boolean isEnabled() {
return getPage()!=null &&super.isEnabled();
}
}
private IContributionItem getZoomMenu() {
ToolbarSubmenuAction zoomMenu = new ToolbarSubmenuAction("Zoom", Activator.getImageDescriptor(ICON_PATH + "Zoom.png")); //$NON-NLS-2$
zoomMenu.addAction(new ZoomOutAction());
zoomMenu.addAction(new ZoomInAction());
zoomMenu.addAction(new ZoomToActualSizeAction());
zoomMenu.addAction(fitToPageAction);
zoomMenu.addAction(fitToWidthAction);
zoomMenu.addAction(fitToHeightAction);
return new ActionContributionItem(zoomMenu);
}
}