<commit_before>package com.defano.hypertalk.ast.commands;

import com.defano.hypercard.HyperCard;
import com.defano.hypercard.paint.ToolsContext;
import com.defano.hypercard.parts.ToolEditablePart;
import com.defano.hypercard.parts.card.CardLayerPart;
import com.defano.hypercard.parts.model.PartModel;
import com.defano.hypercard.runtime.context.ExecutionContext;
import com.defano.hypercard.runtime.context.PartToolContext;
import com.defano.hypercard.util.ThreadUtils;
import com.defano.hypertalk.ast.common.PartType;
import com.defano.hypertalk.ast.specifiers.PartSpecifier;
import com.defano.hypertalk.ast.expressions.PartExp;
import com.defano.hypertalk.ast.statements.Command;
import com.defano.hypertalk.exception.HtException;
import com.defano.hypertalk.exception.HtSemanticException;
import org.antlr.v4.runtime.ParserRuleContext;

public class SelectPartCmd extends Command {

    private final PartExp part;

    public SelectPartCmd(ParserRuleContext context, PartExp part) {
        super(context, "select");
        this.part = part;
    }

    @Override
    public void onExecute() throws HtException {
        PartSpecifier specifier = this.part.evaluateAsSpecifier();

        if (specifier.getType() == null || (specifier.getType() != PartType.FIELD && specifier.getType() != PartType.BUTTON)) {
            throw new HtSemanticException("Expected a button or field here.");
        }

        PartModel partModel = ExecutionContext.getContext().getPart(specifier);
        CardLayerPart part = HyperCard.getInstance().getDisplayedCard().getPart(partModel);

        ThreadUtils.invokeAndWaitAsNeeded(() -> {
            ToolsContext.getInstance().forceToolSelection(specifier.getType().getEditTool(), false);
            PartToolContext.getInstance().setSelectedPart((ToolEditablePart) part);
        });
    }
}<commit_msg>Focusing stack window when programmatically selecting parts<commit_after>package com.defano.hypertalk.ast.commands;

import com.defano.hypercard.HyperCard;
import com.defano.hypercard.paint.ToolsContext;
import com.defano.hypercard.parts.ToolEditablePart;
import com.defano.hypercard.parts.card.CardLayerPart;
import com.defano.hypercard.parts.model.PartModel;
import com.defano.hypercard.runtime.context.ExecutionContext;
import com.defano.hypercard.runtime.context.PartToolContext;
import com.defano.hypercard.util.ThreadUtils;
import com.defano.hypercard.window.WindowManager;
import com.defano.hypertalk.ast.common.PartType;
import com.defano.hypertalk.ast.specifiers.PartSpecifier;
import com.defano.hypertalk.ast.expressions.PartExp;
import com.defano.hypertalk.ast.statements.Command;
import com.defano.hypertalk.exception.HtException;
import com.defano.hypertalk.exception.HtSemanticException;
import org.antlr.v4.runtime.ParserRuleContext;

public class SelectPartCmd extends Command {

    private final PartExp part;

    public SelectPartCmd(ParserRuleContext context, PartExp part) {
        super(context, "select");
        this.part = part;
    }

    @Override
    public void onExecute() throws HtException {
        PartSpecifier specifier = this.part.evaluateAsSpecifier();

        if (specifier.getType() == null || (specifier.getType() != PartType.FIELD && specifier.getType() != PartType.BUTTON)) {
            throw new HtSemanticException("Expected a button or field here.");
        }

        PartModel partModel = ExecutionContext.getContext().getPart(specifier);
        CardLayerPart part = HyperCard.getInstance().getDisplayedCard().getPart(partModel);

        ThreadUtils.invokeAndWaitAsNeeded(() -> {
            WindowManager.getStackWindow().requestFocus();

            ToolsContext.getInstance().forceToolSelection(specifier.getType().getEditTool(), false);
            PartToolContext.getInstance().setSelectedPart((ToolEditablePart) part);
        });
    }
}
{'fraction_non_alphanumeric': 0.10874089490114464, 'fraction_numerical': 0.0005202913631633715, 'mean_word_length': 4.469416785206259, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6987706', 'n_tokens_mistral': 1114, 'n_tokens_neox': 1090, 'n_words': 179}