/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2016 Neil C Smith. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 3 for more details. * * You should have received a copy of the GNU General Public License version 3 * along with this work; if not, see http://www.gnu.org/licenses/ * * * Please visit http://neilcsmith.net if you need additional information or * have any questions. */ package net.neilcsmith.praxis.live.pxr; import java.awt.EventQueue; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import net.neilcsmith.praxis.live.core.api.Syncable; import net.neilcsmith.praxis.live.model.ComponentProxy; import net.neilcsmith.praxis.live.model.ContainerProxy; import net.neilcsmith.praxis.live.util.AbstractTask; import org.netbeans.api.progress.ProgressHandle; import org.openide.util.RequestProcessor; /** * * @author Neil C Smith (http://neilcsmith.net) */ public class SyncTask extends AbstractTask { private final static Logger LOG = Logger.getLogger(SyncTask.class.getName()); private final static RequestProcessor RP = new RequestProcessor(); public final static long DEFAULT_SYNC_MS = 500; private final Set<ComponentProxy> components; private final List<ComponentProxy> syncing; private final long milliseconds; private ProgressHandle ph; public SyncTask(Set<ComponentProxy> components) { this(components, DEFAULT_SYNC_MS); } public SyncTask(Set<ComponentProxy> components, long milliseconds) { this.components = components; this.syncing = new ArrayList<>(); this.milliseconds = milliseconds < 10 ? 10 : milliseconds > 2000 ? 2000 : milliseconds; } @Override protected void handleExecute() throws Exception { LOG.log(Level.FINE, "Starting sync on {0}", components); ph = ProgressHandle.createHandle("Syncing"); ph.setInitialDelay(0); ph.start(); syncComponents(); RP.schedule(new Runnable() { @Override public void run() { EventQueue.invokeLater(new Runnable() { @Override public void run() { finish(); } }); } }, milliseconds, TimeUnit.MILLISECONDS); } private void finish() { unsyncComponents(); ph.finish(); ph = null; updateState(State.COMPLETED); } private void syncComponents() { components.stream().forEach(this::addComponentAndChildren); syncing.stream().forEach(cmp -> { Syncable sync = cmp.getLookup().lookup(Syncable.class); if (sync != null) { LOG.log(Level.FINE, "Adding sync to {0}", cmp.getAddress()); sync.addKey(this); } }); } private void addComponentAndChildren(ComponentProxy component) { syncing.add(component); if (component instanceof ContainerProxy) { ContainerProxy container = (ContainerProxy) component; for (String id : container.getChildIDs()) { addComponentAndChildren(container.getChild(id)); } } } private void unsyncComponents() { syncing.stream().forEach(cmp -> { Syncable sync = cmp.getLookup().lookup(Syncable.class); if (sync != null) { LOG.log(Level.FINE, "Removing sync from {0}", cmp.getAddress()); sync.removeKey(this); } }); syncing.clear(); } }