/* * Carrot2 project. * * Copyright (C) 2002-2016, Dawid Weiss, Stanisław Osiński. * All rights reserved. * * Refer to the full license file "carrot2.LICENSE" * in the root folder of the repository checkout or at: * http://www.carrot2.org/carrot2.LICENSE */ package org.carrot2.workbench.core.ui; import java.io.StringWriter; import java.net.URL; import java.util.*; import org.apache.commons.lang.StringUtils; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.runtime.RuntimeInstance; import org.carrot2.core.*; import org.carrot2.core.attribute.AttributeNames; import org.carrot2.workbench.core.WorkbenchCorePlugin; import org.carrot2.workbench.core.helpers.Utils; import org.carrot2.workbench.velocity.VelocityInitializer; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.*; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.browser.IWorkbenchBrowserSupport; import org.slf4j.LoggerFactory; /** * Simple SWT composite displaying a list of {@link Document} or {@link Cluster} objects. */ public final class DocumentList extends Composite { /** * Bundle folder in which templates are located. */ private static final String TEMPLATES_PREFIX = "/templates/"; /** * Template displayed in {@link #show(ProcessingResult)}. */ private static final String TEMPLATE_PROCESSING_RESULT = "processing-result.vm"; /** * Template displayed in {@link #clear()}. */ private static final String TEMPLATE_CLEAR = "clear.vm"; /** * Template displayed in {@link #show(Cluster...)}. */ private static final String TEMPLATE_CLUSTERS = "clusters.vm"; /** * Lazy velocity initialization flag. */ private static boolean initialized; /** * Internal HTML browser for displaying rendered results. */ private Browser browser; /** * Maximum number of documents to display for a search result. */ private int maxDisplayPerResult = 1000; /** * Maximum number of documents to display per cluster. */ private int maxDisplayPerCluster = 1000; /** * Velocity instance for processing templates. */ private static RuntimeInstance velocity; /* * */ public DocumentList(Composite parent, int style) { super(parent, style); synchronized (this.getClass()) { if (!initialized) { velocity = VelocityInitializer.createInstance( WorkbenchCorePlugin.PLUGIN_ID, TEMPLATES_PREFIX); initialized = true; } } createComponents(); } /** * Show a template displaying all results from a {@link ProcessingResult}. We simply * display all documents available (no explicit cluster markers). */ public void show(ProcessingResult result) { final VelocityContext context = VelocityInitializer.createContext(); context.put("result", result); if (result.getAttributes().get(AttributeNames.RESULTS_TOTAL) != null) { final long total = (Long) result.getAttributes().get( AttributeNames.RESULTS_TOTAL); context.put(AttributeNames.RESULTS_TOTAL + "-formatted", String.format(Locale.ENGLISH, "%1$,d", total)); } String query = (String) result.getAttributes().get("query"); if (StringUtils.isEmpty(query)) { query = ""; } context.put("query", query); context.put("maxDisplay", maxDisplayPerResult); update(context, TEMPLATE_PROCESSING_RESULT); } /** * Show a template displaying one or more {@link Cluster}s. */ public void show(Cluster... clusters) { if (clusters.length == 0) { clear(); } else { final VelocityContext context = VelocityInitializer.createContext(); context.put("clusters", Arrays.asList(clusters)); context.put("maxDisplay", maxDisplayPerCluster); update(context, TEMPLATE_CLUSTERS); } } /** * Clear the display. */ public void clear() { update(null, TEMPLATE_CLEAR); } /* * */ @Override public void dispose() { browser.dispose(); } /** * Update browser with new HTML rendered using Velocity template. */ private void update(VelocityContext context, String templateName) { long start = System.currentTimeMillis(); long merged = 0; StringWriter sw = new StringWriter(); try { final Template template = velocity.getTemplate(templateName, "UTF-8"); template.merge(context, sw); merged = System.currentTimeMillis() - start; } catch (Exception e) { Utils.logError("Error while loading template", e, true); return; } browser.setText(sw.toString()); long displayed = System.currentTimeMillis() - start - merged; LoggerFactory.getLogger(DocumentList.class).debug( String.format(Locale.ENGLISH, "Velocity [rendering: %.2f, display: %.2f]", merged / 1000.0, displayed / 1000.0)); } /** * Create GUI components. */ private void createComponents() { this.setLayout(new FillLayout()); browser = BrowserFacade.createNew(this, SWT.NONE); /* * Attach to location change event and open * a new browser instead of changing internal browser's location. */ browser.addLocationListener(new LocationAdapter() { @Override public void changing(LocationEvent event) { // Browser was refreshed using setText() method if (event.location.equals("about:blank")) { return; } try { WorkbenchCorePlugin.getDefault().getWorkbench().getBrowserSupport() .createBrowser( IWorkbenchBrowserSupport.AS_EDITOR | IWorkbenchBrowserSupport.LOCATION_BAR | IWorkbenchBrowserSupport.NAVIGATION_BAR | IWorkbenchBrowserSupport.STATUS, null, null, null) .openURL(new URL(event.location)); } catch (Exception e) { Utils.logError("Couldn't open internal browser", e, true); } // Cancel the internal event so that we don't open the new location. event.doit = false; } }); } }