/******************************************************************************* * Copyright (c) 2007, 2010 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 *******************************************************************************/ package org.simantics.browsing.ui.graph.impl.contribution; import org.simantics.browsing.ui.BuiltinKeys.LabelDecoratorKey; import org.simantics.browsing.ui.DataSource; import org.simantics.browsing.ui.NodeContext; import org.simantics.browsing.ui.PrimitiveQueryUpdater; import org.simantics.browsing.ui.content.LabelDecorator; import org.simantics.browsing.ui.graph.impl.request.ResourceQuery; import org.simantics.db.ReadGraph; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.Listener; import org.simantics.db.procedure.Procedure; import org.simantics.utils.ui.ErrorLogger; public abstract class FinalLabelDecoratorContributionImpl extends LabelDecorator.Stub { final LabelDecorator FRESH = new LabelDecorator.Stub(); final LabelDecorator PENDING = new LabelDecorator.Stub(); final LabelDecorator NO_DECORATION = new LabelDecorator.Stub(); protected final PrimitiveQueryUpdater updater; private final ResourceQuery labelQuery; private final LabelDecoratorKey key; /** * The current decorator result produced for this contribution. The value * should never be null, but one of {@link #FRESH}, * {@link #PENDING}, {@link #NO_DECORATION} instead. */ protected LabelDecorator decorator = FRESH; final protected NodeContext context; public Object getIdentity(LabelDecoratorKey key) { return key; } private void request() { final DataSource source = updater.getDataSource(ReadGraph.class); assert(source != null); final Procedure procedure = createProcedure(); source.schedule(graph -> { if(procedure instanceof Listener) graph.asyncRequest(labelQuery, (Listener)procedure); else graph.asyncRequest(labelQuery, procedure); }); } @Override public Color_ decorateBackground(Color_ color, String column, int itemIndex) { if(FRESH == decorator) { decorator = PENDING; request(); } return decorator.decorateBackground(color, column, itemIndex); } @Override public Font_ decorateFont(Font_ font, String column, int itemIndex) { if(FRESH == decorator) { decorator = PENDING; request(); } return decorator.decorateFont(font, column, itemIndex); } @Override public String decorateLabel(String label, String column, int itemIndex) { if(FRESH == decorator) { decorator = PENDING; request(); } return decorator.decorateLabel(label, column, itemIndex); } @Override public Color_ decorateForeground(Color_ color, String column, int itemIndex) { if(FRESH == decorator) { decorator = PENDING; request(); } return decorator.decorateForeground(color, column, itemIndex); } public FinalLabelDecoratorContributionImpl(final PrimitiveQueryUpdater updater, final NodeContext context, final LabelDecoratorKey key) { this.updater = updater; this.context = context; this.key = key; labelQuery = new ResourceQuery(getIdentity(key), context) { @Override public LabelDecorator perform(ReadGraph graph) throws DatabaseException { try { return getDecorator(graph, context); } catch (DatabaseException e) { throw e; } catch (Throwable t) { ErrorLogger.defaultLogError("LazyGraphLabeler.labelQuery produced unexpected exception.", t); return null; } } @Override public String toString() { return FinalLabelDecoratorContributionImpl.this + " with context " + context; } }; } protected Procedure createProcedure() { return new Procedure() { @Override public void execute(LabelDecorator result) { replaceResult(result); } @Override public void exception(Throwable t) { ErrorLogger.defaultLogError("LazyContributionImpl.childQuery failed, see exception for details.", t); } }; } protected void replaceResult(LabelDecorator result) { // Never let decorator become null, use a stub decorator instead. if (result == null) result = NO_DECORATION; decorator = result; updater.scheduleReplace(context, key, this); } // OVERRIDE public abstract LabelDecorator getDecorator(ReadGraph graph, NodeContext context) throws DatabaseException; }