+/*******************************************************************************
+ * Copyright (c) 2007, 2014 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum Oy
+ *******************************************************************************/
+package org.simantics.workbench.search.impl;
+
+import java.net.URL;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+import org.simantics.Simantics;
+import org.simantics.db.Session;
+import org.simantics.db.layer0.genericrelation.Dependencies;
+import org.simantics.db.layer0.request.ActiveModels;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.db.management.ISessionContextChangedListener;
+import org.simantics.db.management.SessionContextChangedEvent;
+import org.simantics.db.service.LifecycleSupport;
+import org.simantics.utils.ui.SWTUtils;
+import org.simantics.workbench.search.ISearchService;
+import org.simantics.workbench.search.ISearchService.ResultBrowser;
+import org.simantics.workbench.search.SearchQuery;
+
+/**
+ * A very non-configurable Web browser view for search trim.
+ *
+ * @author Tuukka Lehtonen
+ */
+public class BrowserView extends ViewPart {
+
+ /**
+ * ID of this view's plug-in extension.
+ */
+ public static final String ID = "org.simantics.workbench.search.browser";
+
+ /**
+ * Used as a property of this view to keep track of the last search query
+ * performed with this view. This information is needed to know whether or
+ * not to initialize the view with default contents after it has been
+ * created. This depends on whether the creation was caused by a simple
+ * activation of the view or an actual search being performed.
+ */
+ public static final String LAST_QUERY_PROPERTY = "org.simantics.workbench.search.browser.lastQuery";
+
+ private Browser browser;
+ private boolean disposed;
+ private ActiveModelsListener currentListener;
+
+ @Override
+ public void createPartControl(Composite parent) {
+ browser = new org.eclipse.swt.browser.Browser(parent, SWT.NONE);
+
+ // Ensure the view receives some browser content even when no searches
+ // have been performed yet.
+ scheduleInitializeViewContent(false);
+
+ // Make sure that the contents of the view are reset every time the set
+ // of active models changes. This must be because what is searchable depends
+ // completely on the active models. When there is no active model, the search
+ // will find nothing.
+ Simantics.getSessionContextProvider().addContextChangedListener(sessionListener);
+ trackActiveModels(Simantics.peekSession());
+ }
+
+ private ISessionContextChangedListener sessionListener = new ISessionContextChangedListener() {
+ @Override
+ public void sessionContextChanged(SessionContextChangedEvent event) {
+ ISessionContext ctx = event.getNewValue();
+ final Session newSession = ctx != null ? ctx.peekSession() : null;
+ // Synchronize session changes to the UI thread to keep threading more predictable.
+ SWTUtils.asyncExec(browser, new Runnable() {
+ @Override
+ public void run() {
+ if (!disposed)
+ trackActiveModels(newSession);
+ }
+ });
+ }
+ };
+
+ private void trackActiveModels(Session session) {
+ if (currentListener != null) {
+ currentListener.dispose();
+ currentListener = null;
+ }
+ if (session != null) {
+
+ LifecycleSupport lfs = session.peekService(LifecycleSupport.class);
+ if (lfs == null)
+ return;
+ if (lfs.isClosed())
+ return;
+
+ ActiveModelsListener listener = new ActiveModelsListener(new Runnable() {
+ @Override
+ public void run() {
+ scheduleInitializeViewContent(true);
+ }
+ });
+
+ // Make sure that the listener is disposed if the session is disposed.
+ session.registerService(ActiveModelsListener.class, listener);
+ session.asyncRequest(new ActiveModels(Simantics.getProjectResource()), listener);
+ this.currentListener = listener;
+ }
+ }
+
+ protected void scheduleInitializeViewContent(final boolean force) {
+ SWTUtils.asyncExec(browser, new Runnable() {
+ @Override
+ public void run() {
+ if (disposed)
+ return;
+ // If SearchServiceImpl hasn't performed any queries yet,
+ // then we shall initialize the view contents at this point.
+ String lastQuery = getPartProperty(LAST_QUERY_PROPERTY);
+ if (force || lastQuery == null)
+ initializeViewContent();
+ }
+ });
+ }
+
+ protected void initializeViewContent() {
+ SearchQuery query = new SearchQuery("");
+ query.setSearchFlag(Dependencies.FIELD_NAME_SEARCH, "on");
+ query.setSearchFlag(Dependencies.FIELD_TYPES_SEARCH, "on");
+ ISearchService searchService = (ISearchService) PlatformUI.getWorkbench().getService(ISearchService.class);
+ if (searchService != null)
+ searchService.performQuery(query, ResultBrowser.VIEW, false);
+ }
+
+ @Override
+ public void dispose() {
+ disposed = true;
+ super.dispose();
+ }
+
+ public boolean isDisposed() {
+ return disposed;
+ }
+
+ @Override
+ public void setFocus() {
+ browser.setFocus();
+ }
+
+ public org.eclipse.swt.browser.Browser getBrowser() {
+ return browser;
+ }
+
+ public void setUrl(URL url) {
+ getBrowser().setUrl(url.toString());
+ }
+
+ @Override
+ public void setContentDescription(String description) {
+ super.setContentDescription(description);
+ }
+
+}