<NME> selection-changed-action.cocoascript
<BEF> @import 'actions/action-inventory.cocoascript'
@import 'actions/view-inventory.cocoascript'
@import 'actions/statistics-inventory.cocoascript'
@import 'run-actions.cocoascript'
@import 'lib.js'


function SelectionInventory(type) {
    this.type = type
    this.artboards = NSMutableArray.new()
    this.layers = NSMutableArray.new()
}

function SelectionInventory(type, artboards) {
    this.type = type
    this.artboards = NSMutableArray.new()
    this.layers = NSMutableArray.new()

    if (artboards != nil) { this.artboards = artboards}
}

function SelectionInventory(type, artboards, layers) {
    this.type = type
    this.artboards = NSMutableArray.new()
    this.layers = NSMutableArray.new()

    if (artboards != nil) { this.artboards = artboards}
    if (layers != nil) { this.layers = layers}
}





var onSelectionChanged = function(context) {
    SelectionInventory.selectionChangedHandler()
};



SelectionInventory.selectionChangedHandler = function() {
  coscript.setShouldKeepAround(true);

  coscript.scheduleWithInterval_jsFunction(0.05,function() {
      var localTime = [NSDate date]
      currentDocument = NSDocumentController.sharedDocumentController().currentDocument()

      if (currentDocument == nil) {
        coscript.setShouldKeepAround(false);
        return
      }

      var localSelection = currentDocument.selectedLayers().layers();
      var selectionInventoryInstance = SelectionInventory.analyseActionType(localSelection)
      // log(selectionInventoryInstance)
      // var currentSelectionType = selectionInventoryInstance.type
      // var selectionTitle = ""
      // if (currentSelectionType == 0) { selectionTitle = "Select Layers" }
      // else if (currentSelectionType == 1) { selectionTitle = "Layer / All States" }
      // else if (currentSelectionType == 2) { selectionTitle = "Selected States" }
      // else if (currentSelectionType == 3) { selectionTitle = "Layers / All States for Layers" }
      // else if (currentSelectionType == 4) { selectionTitle = "Selected States for Layers" }
      log("a: " + [[NSDate date] timeIntervalSinceDate:localTime])

      var localMode = ToolbarInventory.toolbarMode()
      // log("localMode: " + localMode)
      if (localMode == Status.toolbarModeImport()) {
        ToolbarInventory.updateImportButtons(selectionInventoryInstance.type)

        var localLayers = selectionInventoryInstance.layers
        if (selectionInventoryInstance.type == 2) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name()) }
        else if (localLayers.count() == 2) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name() + ", " + localLayers.objectAtIndex(1).name()) }
        else if (localLayers.count() == 1) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name()) }
        else if (localLayers.count() > 0) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name() + ", " + localLayers.objectAtIndex(1).name() + " and " + (localLayers.count()-2) + " more") }
        else { ToolbarInventory.updateSelectionLabelStringValue(ViewInventory.placeHolderImport()) }
      }
      else if (localMode == Status.toolbarModeScene()) {
          // log("Found correct action: " + selectionInventoryInstance.type)
          ToolbarInventory.updateSceneButtons(selectionInventoryInstance.type)
      }


      // StatisticsInventory.setStatus(2)
      log("b: " + [[NSDate date] timeIntervalSinceDate:localTime])
      coscript.setShouldKeepAround(false);
  });
}


// 0 – Select layers
// 1 – layer / all states
// 1 – layer / all states
// 2 – selected states
// 3 – layers / all states for layers
// 4 – selected states for layers
// 5 – Scene
// 6 – Scene for selected artboards
// 7 – Expired

SelectionInventory.analyseActionType = function(selection) {
    if (!DemoInventory.isRegistered() && DemoInventory.actionsLeft() <= 0) { return new SelectionInventory(7) }


    var localLayers = NSMutableArray.new()
    var localArtboards = NSMutableArray.new()

    for (var i = 0; i < selection.count(); i++) {
        var currentLayerClassName = [[selection objectAtIndex:i] className]
        if (TypeInventory.isArtboardType(currentLayerClassName)) { localArtboards.addObject([selection objectAtIndex:i]) }
        else { localLayers.addObject([selection objectAtIndex:i]) }
    }

    // for Keynote only
    if (StatisticsInventory.getStatus() == Status.simulateID() || (ToolbarInventory.toolbarMode() == Status.toolbarModeScene() && (StatisticsInventory.getStatus() != Status.generateID() || StatisticsInventory.getStatus() != Status.replicateID()))) {
        if (localArtboards.count() < 1) { return new SelectionInventory(5, currentDocument.currentPage().artboards()) }
        return new SelectionInventory(6, localArtboards)
    }

    if (localLayers.count() < 1) { return new SelectionInventory(0) }

    var isSameName = true
    if (localLayers.count() > 0) {
    if (localLayers.count() < 1 || !hasParentArtboard) { return new SelectionInventory(0) }

    var isSameName = true
    if (localLayers.count() > 0) {
        var currentLayerName = [[localLayers firstObject] name]
        for (var i = 1; i < localLayers.count(); i++) {
            var currentLayer = [localLayers objectAtIndex:i]
            if (![currentLayerName isEqualToString:[currentLayer name]]) {
                isSameName = false
                break;
            }
        }
    }

    var additionalArtboards = NSMutableArray.new()
    for (var i = 0; i < localLayers.count(); i++) {
        var currentLayer = [localLayers objectAtIndex:i]
        var currentLayerArtboard = TypeInventory.findParentArtboard(currentLayer)
        if (TypeInventory.isArtboardType([currentLayerArtboard className])) { additionalArtboards.addObject(currentLayerArtboard) }
    }

    for (var i = 0; i < additionalArtboards.count(); i++) {
        var shouldAddCurrentArtboard = true
        var currentArtboard = [additionalArtboards objectAtIndex:i]

        for (var j = 0; j < localArtboards.count(); j++) {
            var comparableArtboard = [localArtboards objectAtIndex:j]
            if ([[comparableArtboard name] isEqualToString:[currentArtboard name]] &&
                [comparableArtboard hash] == [currentArtboard hash]) {
                    shouldAddCurrentArtboard = false
                    break;
                }
        }

        if (shouldAddCurrentArtboard) { localArtboards.addObject(currentArtboard) }
    }

    // log("L: " + localLayers.count() + ", on A:" + localArtboards.count() + ". Same?" + isSameName)

    var type = -1
    if (localArtboards.count() == 1) { type = isSameName ? 1 : 3 }
    else if (localArtboards.count() > 1) { type = isSameName ? 2 : 4 }
    else { type = 0 }

    return new SelectionInventory(type, localArtboards, localLayers)
}

<MSG> Selection analyser can be sync/async

– Changed selectionChanged function to be ready to work as sync/async
– Empty states even if we select several layers without any Artboards
as parents

<DFF> @@ -33,59 +33,60 @@ function SelectionInventory(type, artboards, layers) {
 
 
 var onSelectionChanged = function(context) {
-    SelectionInventory.selectionChangedHandler()
+  var asyncing = true
+  coscript.setShouldKeepAround(true);
+  coscript.scheduleWithInterval_jsFunction(0.05, SelectionInventory.asyncSelectionHandler(asyncing));
 };
 
 
+SelectionInventory.asyncSelectionHandler = function(asyncing) {
+    var localTime = [NSDate date]
+    currentDocument = NSDocumentController.sharedDocumentController().currentDocument()
 
-SelectionInventory.selectionChangedHandler = function() {
-  coscript.setShouldKeepAround(true);
+    if (currentDocument == nil) {
+      if (asyncing) { coscript.setShouldKeepAround(false); }
+      return
+    }
+
+    var localSelection = currentDocument.selectedLayers().layers();
+    var selectionInventoryInstance = SelectionInventory.analyseActionType(localSelection)
+    // log(selectionInventoryInstance)
+    // var currentSelectionType = selectionInventoryInstance.type
+    // var selectionTitle = ""
+    // if (currentSelectionType == 0) { selectionTitle = "Select Layers" }
+    // else if (currentSelectionType == 1) { selectionTitle = "Layer / All States" }
+    // else if (currentSelectionType == 2) { selectionTitle = "Selected States" }
+    // else if (currentSelectionType == 3) { selectionTitle = "Layers / All States for Layers" }
+    // else if (currentSelectionType == 4) { selectionTitle = "Selected States for Layers" }
+    log("a: " + [[NSDate date] timeIntervalSinceDate:localTime])
+
+    var localMode = ToolbarInventory.toolbarMode()
+    // log("localMode: " + localMode)
+    if (localMode == Status.toolbarModeImport()) {
+      ToolbarInventory.updateImportButtons(selectionInventoryInstance.type)
+
+      var localLayers = selectionInventoryInstance.layers
+      if (selectionInventoryInstance.type == 2) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name()) }
+      else if (localLayers.count() == 2) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name() + ", " + localLayers.objectAtIndex(1).name()) }
+      else if (localLayers.count() == 1) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name()) }
+      else if (localLayers.count() > 0) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name() + ", " + localLayers.objectAtIndex(1).name() + " and " + (localLayers.count()-2) + " more") }
+      else { ToolbarInventory.updateSelectionLabelStringValue(ViewInventory.placeHolderImport()) }
+    }
+    else if (localMode == Status.toolbarModeScene()) {
+        // log("Found correct action: " + selectionInventoryInstance.type)
+        ToolbarInventory.updateSceneButtons(selectionInventoryInstance.type)
+    }
 
-  coscript.scheduleWithInterval_jsFunction(0.05,function() {
-      var localTime = [NSDate date]
-      currentDocument = NSDocumentController.sharedDocumentController().currentDocument()
-
-      if (currentDocument == nil) {
-        coscript.setShouldKeepAround(false);
-        return
-      }
-
-      var localSelection = currentDocument.selectedLayers().layers();
-      var selectionInventoryInstance = SelectionInventory.analyseActionType(localSelection)
-      // log(selectionInventoryInstance)
-      // var currentSelectionType = selectionInventoryInstance.type
-      // var selectionTitle = ""
-      // if (currentSelectionType == 0) { selectionTitle = "Select Layers" }
-      // else if (currentSelectionType == 1) { selectionTitle = "Layer / All States" }
-      // else if (currentSelectionType == 2) { selectionTitle = "Selected States" }
-      // else if (currentSelectionType == 3) { selectionTitle = "Layers / All States for Layers" }
-      // else if (currentSelectionType == 4) { selectionTitle = "Selected States for Layers" }
-      log("a: " + [[NSDate date] timeIntervalSinceDate:localTime])
-
-      var localMode = ToolbarInventory.toolbarMode()
-      // log("localMode: " + localMode)
-      if (localMode == Status.toolbarModeImport()) {
-        ToolbarInventory.updateImportButtons(selectionInventoryInstance.type)
-
-        var localLayers = selectionInventoryInstance.layers
-        if (selectionInventoryInstance.type == 2) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name()) }
-        else if (localLayers.count() == 2) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name() + ", " + localLayers.objectAtIndex(1).name()) }
-        else if (localLayers.count() == 1) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name()) }
-        else if (localLayers.count() > 0) { ToolbarInventory.updateSelectionLabelStringValue(localLayers.firstObject().name() + ", " + localLayers.objectAtIndex(1).name() + " and " + (localLayers.count()-2) + " more") }
-        else { ToolbarInventory.updateSelectionLabelStringValue(ViewInventory.placeHolderImport()) }
-      }
-      else if (localMode == Status.toolbarModeScene()) {
-          // log("Found correct action: " + selectionInventoryInstance.type)
-          ToolbarInventory.updateSceneButtons(selectionInventoryInstance.type)
-      }
-
-
-      // StatisticsInventory.setStatus(2)
-      log("b: " + [[NSDate date] timeIntervalSinceDate:localTime])
-      coscript.setShouldKeepAround(false);
-  });
+
+    // StatisticsInventory.setStatus(2)
+    log("b: " + [[NSDate date] timeIntervalSinceDate:localTime])
+    if (asyncing) { coscript.setShouldKeepAround(false); }
 }
 
+// SelectionInventory.selectionChangedHandler = function() {
+//
+// }
+
 
 // 0 – Select layers
 // 1 – layer / all states
@@ -103,20 +104,26 @@ SelectionInventory.analyseActionType = function(selection) {
 
     var localLayers = NSMutableArray.new()
     var localArtboards = NSMutableArray.new()
+    var hasParentArtboard = false
 
     for (var i = 0; i < selection.count(); i++) {
         var currentLayerClassName = [[selection objectAtIndex:i] className]
         if (TypeInventory.isArtboardType(currentLayerClassName)) { localArtboards.addObject([selection objectAtIndex:i]) }
-        else { localLayers.addObject([selection objectAtIndex:i]) }
+        else {
+            localLayers.addObject([selection objectAtIndex:i])
+            if (!hasParentArtboard) {
+                var localParent = TypeInventory.findParentArtboard([selection objectAtIndex:i])
+                if (localParent != nil && TypeInventory.isArtboardType(localParent.className())) { hasParentArtboard = true }
+            }
+        }
     }
-
     // for Keynote only
     if (StatisticsInventory.getStatus() == Status.simulateID() || (ToolbarInventory.toolbarMode() == Status.toolbarModeScene() && (StatisticsInventory.getStatus() != Status.generateID() || StatisticsInventory.getStatus() != Status.replicateID()))) {
         if (localArtboards.count() < 1) { return new SelectionInventory(5, currentDocument.currentPage().artboards()) }
         return new SelectionInventory(6, localArtboards)
     }
 
-    if (localLayers.count() < 1) { return new SelectionInventory(0) }
+    if (localLayers.count() < 1 || !hasParentArtboard) { return new SelectionInventory(0) }
 
     var isSameName = true
     if (localLayers.count() > 0) {

Selection analyser can be sync/async