com.willwinder.universalgcodesender.uielements.macros.MacroActionPanel.java Source code

Java tutorial

Introduction

Here is the source code for com.willwinder.universalgcodesender.uielements.macros.MacroActionPanel.java

Source

/*
Copywrite 2016 Will Winder
    
This file is part of Universal Gcode Sender (UGS).
    
UGS is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
    
UGS 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 for more details.
    
You should have received a copy of the GNU General Public License
along with UGS.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.willwinder.universalgcodesender.uielements.macros;

import com.willwinder.universalgcodesender.MacroHelper;
import com.willwinder.universalgcodesender.listeners.UGSEventListener;
import com.willwinder.universalgcodesender.model.BackendAPI;
import com.willwinder.universalgcodesender.types.Macro;
import com.willwinder.universalgcodesender.utils.GUIHelpers;
import com.willwinder.universalgcodesender.utils.Settings;
import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

public class MacroActionPanel extends JPanel implements UGSEventListener {

    private static final int INSET = 10;
    private static final int PADDING = 10;

    private final BackendAPI backend;
    private final List<JButton> customGcodeButtons = new ArrayList<>();
    private final ArrayList<Macro> macros = new ArrayList<>();
    JPanel macroPanel = new JPanel();

    // Indicates that the macro list needs to be refreshed.
    private boolean macrosDirty = true;

    public MacroActionPanel(BackendAPI backend) {
        if (backend == null) {
            throw new RuntimeException("BackendAPI must be provided.");
        }
        setMinimumSize(new Dimension(50, 0));
        this.backend = backend;
        backend.addUGSEventListener(this);

        // Insert a scrollpane in case the buttons wont fit.
        JScrollPane scrollPane = new JScrollPane(macroPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        scrollPane.setBorder(BorderFactory.createEmptyBorder());
        setLayout(new BorderLayout());
        add(scrollPane, BorderLayout.CENTER);
    }

    @Override
    public void doLayout() {
        Settings s = backend.getSettings();

        // Lookup macros.
        if (macrosDirty) {
            Integer lastMacroIndex = s.getLastMacroIndex() + 1;
            macros.clear();
            for (int i = 0; i < lastMacroIndex; i++) {
                Macro m = s.getMacro(i);
                if (StringUtils.isNotEmpty(m.getGcode())) {
                    macros.add(s.getMacro(i));
                }
            }
        }

        // Cache the largest width amongst the buttons.
        int maxWidth = 0;
        int maxHeight = 0;

        // Create buttons.
        for (int i = 0; i < macros.size(); i++) {
            final int index = i;
            Macro macro = macros.get(i);
            JButton button;
            if (customGcodeButtons.size() <= i) {
                button = new JButton(i + "");
                button.setEnabled(false);
                customGcodeButtons.add(button);
                // Add action listener
                button.addActionListener((ActionEvent evt) -> {
                    customGcodeButtonActionPerformed(index);
                });
            } else {
                button = customGcodeButtons.get(i);
            }

            if (!StringUtils.isEmpty(macro.getName())) {
                button.setText(macro.getName());
            } else if (!StringUtils.isEmpty(macro.getDescription())) {
                button.setText(macro.getDescription());
            }

            if (!StringUtils.isEmpty(macro.getDescription())) {
                button.setToolTipText(macro.getDescription());
            }

            if (button.getPreferredSize().width > maxWidth)
                maxWidth = button.getPreferredSize().width;
            if (button.getPreferredSize().height > maxHeight)
                maxHeight = button.getPreferredSize().height;
        }

        // If button count was reduced, clear out any extras.
        if (customGcodeButtons.size() > macros.size()) {
            this.macroPanel.removeAll();
            this.macroPanel.repaint();
            for (int i = customGcodeButtons.size(); i > macros.size(); i--) {
                JButton b = customGcodeButtons.remove(i - 1);
            }
        }

        // Calculate columns/rows which can fit in the space we have.
        int columns = (getWidth() - (2 * INSET)) / (maxWidth + PADDING);
        int rows = (getHeight() - (2 * INSET)) / (maxHeight + PADDING);

        // At least one column.
        columns = Math.max(columns, 1);

        // Update number of rows if more are needed.
        if (columns * rows < customGcodeButtons.size()) {
            rows = customGcodeButtons.size() / columns;
            if (customGcodeButtons.size() % columns != 0)
                rows++;
        }

        // Layout for buttons.
        StringBuilder columnConstraint = new StringBuilder();
        for (int i = 0; i < columns; i++) {
            if (i > 0) {
                columnConstraint.append("unrelated");
            }
            columnConstraint.append("[fill, sg 1]");
        }
        MigLayout layout = new MigLayout("fillx, wrap " + columns + ", inset " + INSET,
                columnConstraint.toString());
        macroPanel.setLayout(layout);

        // Put buttons in grid.
        int x = 0;
        int y = 0;
        for (JButton button : customGcodeButtons) {
            macroPanel.add(button, "cell " + x + " " + y);
            y++;
            if (y == rows) {
                x++;
                y = 0;
            }
        }

        super.doLayout();
    }

    private void customGcodeButtonActionPerformed(int macroIndex) {
        Macro macro = backend.getSettings().getMacro(macroIndex);
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    MacroHelper.executeCustomGcode(macro.getGcode(), backend);
                } catch (Exception ex) {
                    GUIHelpers.displayErrorDialog(ex.getMessage());
                }
            }
        });
    }

    private void updateCustomGcodeControls(boolean enabled) {
        for (JButton button : customGcodeButtons) {
            button.setEnabled(enabled);
        }
    }

    @Override
    public void UGSEvent(com.willwinder.universalgcodesender.model.UGSEvent evt) {
        if (evt.isSettingChangeEvent()) {
            macrosDirty = true;
            doLayout();
        } else {
            updateCustomGcodeControls(backend.isIdle());
        }
    }
}