package pl.djvuhtml5.client; import java.util.Arrays; import java.util.List; import com.google.gwt.canvas.client.Canvas; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.Scheduler; import com.google.gwt.dom.client.Element; import com.google.gwt.i18n.client.Dictionary; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; import com.lizardtech.djvu.DjVuInfo; import com.lizardtech.djvu.GMap; import com.lizardtech.djvu.Utils; import com.lizardtech.djvu.text.DjVuText; import pl.djvuhtml5.client.TileRenderer.TileInfo; import pl.djvuhtml5.client.ui.Scrollbar; import pl.djvuhtml5.client.ui.SinglePageLayout; import pl.djvuhtml5.client.ui.TextLayer; import pl.djvuhtml5.client.ui.Toolbar; import pl.djvuhtml5.client.ui.UIHider; /** * Entry point classes define <code>onModuleLoad()</code>. */ public class Djvu_html5 implements EntryPoint { private static final String WELCOME_MESSAGE = "Starting djvu-html5 viewer v0.3.0-beta1 from https://github.com/mateusz-matela/djvu-html5"; private static final String CONTEXT_GLOBAL_VARIABLE = "DJVU_CONTEXT"; private static final List<String> STATUS_IMAGE_ORDER = Arrays.asList(ProcessingContext.STATUS_LOADING, ProcessingContext.STATUS_ERROR); private static Djvu_html5 instance; private Dictionary context; private RootPanel container; private Canvas canvas; private SinglePageLayout pageLayout; private TextLayer textLayer; private Toolbar toolbar; private Scrollbar horizontalScrollbar; private Scrollbar verticalScrollbar; private DataStore dataStore; private BackgroundProcessor backgroundProcessor; private Label statusImage; private String currentStatus; /** * This is the entry point method. */ @Override public void onModuleLoad() { log(WELCOME_MESSAGE); container = RootPanel.get("djvuContainer"); String url = Window.Location.getParameter("file"); if (url == null || url.isEmpty()) url = container.getElement().getAttribute("file"); if (url == null || url.isEmpty()) url = DjvuContext.getIndexFile(); if (url == null || url.isEmpty()) { log("ERROR: No djvu file defined"); return; } DjvuContext.setUrl(Utils.url(GWT.getHostPageBaseURL(), url)); dataStore = new DataStore(); container.add(prepareCanvas()); container.add(textLayer = new TextLayer(this)); container.add(toolbar = new Toolbar()); container.add(horizontalScrollbar = new Scrollbar(true)); container.add(verticalScrollbar = new Scrollbar(false)); container.add(statusImage = new Label()); statusImage.setStyleName("statusImage"); int uiHideDelay = DjvuContext.getUiHideDelay(); if (uiHideDelay > 0) { UIHider uiHider = new UIHider(uiHideDelay, textLayer); uiHider.addUIElement(toolbar, "toolbarHidden"); uiHider.addUIElement(horizontalScrollbar, "scrollbarHidden"); uiHider.addUIElement(verticalScrollbar, "scrollbarHidden"); } if (DjvuContext.getUseWebWorkers() && BackgroundWorker.isAvailable()) { BackgroundWorker.init(new MainProcessingContext()); } else { backgroundProcessor = new BackgroundProcessor(new MainProcessingContext()); } pageLayout = new SinglePageLayout(this); toolbar.setPageLayout(pageLayout); } private Widget prepareCanvas() { canvas = Canvas.createIfSupported(); if (canvas == null) { // TODO throw new RuntimeException("Canvas not supported!"); } canvas.setTabIndex(0); final SimplePanel panel = new SimplePanel(canvas); panel.setStyleName("content"); Window.addResizeHandler(e -> resizeCanvas()); Scheduler.get().scheduleFinally(() -> resizeCanvas()); return panel; } private void resizeCanvas() { Widget panel = canvas.getParent(); int width = panel.getOffsetWidth(); int height = panel.getOffsetHeight(); canvas.setWidth(width + "px"); canvas.setCoordinateSpaceWidth(width); canvas.setHeight(height + "px"); canvas.setCoordinateSpaceHeight(height); if (pageLayout != null) pageLayout.canvasResized(); } public RootPanel getContainer() { return container; } public Canvas getCanvas() { return canvas; } public DataStore getDataStore() { return dataStore; } private void setStatus(String status) { if (status == currentStatus) return; statusImage.setVisible(status != null); if (status != null && !ProcessingContext.STATUS_ERROR.equals(currentStatus)) { int imagePosition = STATUS_IMAGE_ORDER.indexOf(status); statusImage.getElement().getStyle().setProperty("backgroundPosition", -imagePosition * statusImage.getOffsetHeight() + "px 0px"); } if (status == null || !ProcessingContext.STATUS_ERROR.equals(currentStatus)) currentStatus = status; } public SinglePageLayout getPageLayout() { return pageLayout; } /** @return current text layer or {@code null} if disabled. */ public TextLayer getTextLayer() { return textLayer; } public Toolbar getToolbar() { return toolbar; } public Scrollbar getHorizontalScrollbar() { return horizontalScrollbar; } public Scrollbar getVerticalScrollbar() { return verticalScrollbar; } public static native void log(String message) /*-{ console.log(message); }-*/; public static native String getComputedStyleProperty(Element element, String property) /*-{ var cs = $doc.defaultView.getComputedStyle(element, null); return cs.getPropertyValue(property); }-*/; private class MainProcessingContext implements ProcessingContext { @Override public void setStatus(String status) { Djvu_html5.this.setStatus(status); } @Override public void startProcessing() { backgroundProcessor.start(); } @Override public void interruptProcessing() { backgroundProcessor.interrupt(); } @Override public void setPageCount(int pageCount) { dataStore.setPageCount(pageCount); } @Override public void setPageInfo(int pageNum, DjVuInfo info) { dataStore.setPageInfo(pageNum, info); } @Override public void setText(int pageNum, DjVuText text) { dataStore.setText(pageNum, text); } @Override public void setTile(TileInfo tileInfo, GMap bufferGMap) { dataStore.setTile(tileInfo, bufferGMap); } @Override public void releaseTileImages(List<TileInfo> tiles) { dataStore.releaseTileImages(tiles); } } }