/******************************************************************************* * Copyright (c) 2019 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: * Semantum Oy - initial API and implementation *******************************************************************************/ package org.simantics.document.swt.core; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Device; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IWorkbenchSite; import org.simantics.db.common.utils.Logger; import org.simantics.document.server.IEventCommand; import org.simantics.document.server.JSONObject; import org.simantics.document.server.client.DocumentClient; import org.simantics.document.server.client.WidgetData; import org.simantics.document.server.client.WidgetMapping; import org.simantics.document.server.io.AbstractEventHandler; import org.simantics.document.server.io.CommandContext; import org.simantics.document.server.io.CommandContextMutable; import org.simantics.document.server.io.ICommand; import org.simantics.document.swt.core.base.WidgetContainer; import org.simantics.document.swt.core.widget.FillComposite; import org.simantics.ui.colors.Colors; import org.simantics.ui.fonts.Fonts; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.threads.IThreadWorkQueue; import org.simantics.utils.threads.SWTThread; public class SWTDocumentClient extends DocumentClient implements SWTDocument { private Composite container; private IWorkbenchSite site; private ISelectionProvider selectionProvider; private Device device; private IThreadWorkQueue thread; private Map colors = new HashMap(); private Map fonts = new HashMap(); private boolean requireLayout=false; public SWTDocumentClient(WidgetMapping mapping, ISelectionProvider selectionProvider, IWorkbenchSite site, Composite container) { super(mapping, SWTViews.getCommandMapping()); this.container = container; this.site = site; this.selectionProvider = selectionProvider; this.device = container.getDisplay(); this.thread = SWTThread.getThreadAccess(container); JSONObject rootObject = new JSONObject("root"); rootObject.addJSONField("type", "Root"); FillComposite mgr = new FillComposite(); WidgetContainer wc = mgr.createWidget(rootObject); wc.createControl(this, container, rootObject); GridDataFactory.fillDefaults().grab(true, true).minSize(1, 1).applyTo((Control)wc.getControl()); GridLayoutFactory.fillDefaults().applyTo((Composite)wc.getControl()); widgetData.put("root", new WidgetData(this, wc, rootObject)); } @Override public IThreadWorkQueue thread() { return thread; } @Override public Color getColor(org.simantics.datatypes.literal.RGB.Integer descriptor) { Color color = colors.get(descriptor); if(color == null) { color = Colors.swt(device, descriptor); colors.put(descriptor, color); } return color; } @Override public Font getFont(org.simantics.datatypes.literal.Font descriptor) { Font font = fonts.get(descriptor); if(font == null) { font = Fonts.swt(device, descriptor); fonts.put(descriptor, font); } return font; } @Override public ISelectionProvider getSelectionProvider() { return selectionProvider; } @Override public IWorkbenchSite getSite() { return site; } @Override public void post(AbstractEventHandler handler, CommandContextMutable parameters) { handler.handle(parameters); } @Override protected void updateDocument(Collection objects) { assert thread.currentThreadAccess(); super.updateDocument(objects); if(requireLayout) { container.layout(true, true); requireLayout = false; } } @Override protected void updateTree(HashSet updates) { if(updates.isEmpty()) return; for(WidgetData data : updates) { WidgetContainer container = (WidgetContainer)data.widget; Control ctrl = container.getControl(); if (ctrl == null || ctrl.isDisposed()) continue; if(ctrl instanceof Composite) { Composite composite = (Composite)ctrl; for(Control c : composite.getChildren()) { c.dispose(); } } } super.updateTree(updates); for(WidgetData data : widgetData.values()) { WidgetContainer container = (WidgetContainer)data.widget; if(container != null) container.getOrCreateControl(this, data.object); } } @Override public CommandContext handleCommands(List> data, CommandContextMutable context, Object component) { // Build a linked list of commands ArrayList commands = new ArrayList<>(); for(Pair pair : data) { WidgetData d = pair.first; ICommand c = pair.second; IEventCommand p = d.eventCommand(c, null); // if(component != null && p != null) // p.setTrigger(component); if(p != null) { if(!commands.isEmpty()) commands.get(commands.size()-1).setNext(p); commands.add(p); } } // Execute the first command, the linked list handles the rest of them if(!commands.isEmpty()) { try { commands.get(0).handleCommand(context); } finally { } } return context; } @Override public void layout() { requireLayout = true; } @Override public HashMap getWidgetData() { return widgetData; } public void displayError(String error) { Logger.defaultLogError(error); } }