Melhorar código de programa de desenho em Java

Boa noite pessoal!

É o seguinte estou desenvolvendo um pequeno programa de desenho em java que se assemelha com o autoCAD usando Swing.Como faço para melhorar a codificação de programa pois acho que tem muito código duplicado e variáveis repetidas, e gostaria de melhorar o código antes de prosseguir com o programa.Como reduzir linhas de código nesse programa, pois esse código está difícil de dar manutenção

Abaixo as classes do projeto

Desenho.java

package miniCad

import java.awt.BorderLayout;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Desenho extends JPanel implements MouseMotionListener, MouseListener, ActionListener, KeyListener {

    JPanel comandos;
    JPanel menus;
    JPanel areaDesenho;
    JTextField txtBarraComandos;
    final ArrayList<Point> pontos = new ArrayList<>();
    //private final ArrayList<Linhas> linhas = new ArrayList<>();
    final ArrayList<Boolean> linhasVisiveis = new ArrayList<>();
    final ArrayList<Circulo> circulos = new ArrayList<>();
    //int x1, y1, x2, y2;
    // boolean pressionado = false;
    JLabel coordenadas;
    JLabel textoComandos;

JMenuBar barraMenu;
    JMenu menuArquivo;
    JMenu menuDesenhar;
    JMenuItem itemArquivoSair;
    JMenuItem itemDesenharLinha;
    JMenuItem itemDesenharCirculo;
    boolean clickInicial = true;
    boolean clickFinal = false;
    // int i=0;
    boolean teclaL = false;
    boolean linhaAtivada = false;
    boolean click = false;
    int indiceLinha = -1; //inicia com -1 pois quando incrementada dará indice vetor zero,depois um
    boolean teclaC = false;
    boolean circuloAtivado = false;
    int xcentro, ycentro, xcontorno, ycontorno;
    boolean proximoPonto = false;
    int x1, y1, x2, y2; // variáveis marcador de linha

// variáveis distancia e angulo marcador de linha
    double anguloGrausLinha=0;
    double tamanhoLinha=0;
    boolean marcadorLinha=false; // controla a exibição do marcador da linha
    int localizacaoXMarcadorLinha=0;
    int localizacaoYMarcadorLinha=0;
    public Desenho() {
        editarLayout();
        editarMenu();
        addMouseListener(this);
        addMouseMotionListener(this);

    }

public void editarLayout() {
        /*Criando e configurando Layout dos paineis */
        comandos = new JPanel();
        menus = new JPanel();
        setBackground(Color.BLACK);
        setLayout(new BorderLayout());
        menus.setLayout(new BorderLayout());
        comandos.setLayout(new GridLayout(1, 3));
        /*criando e adicionando componentes ao painel comandos*/

        coordenadas = new JLabel("Coordenadas");
        coordenadas.setForeground(Color.RED);

        textoComandos = new JLabel("nenhum comando encontrado");

        comandos.add(coordenadas);
        comandos.add(textoComandos);

        txtBarraComandos = new JTextField(20);

comandos.add(coordenadas);
        comandos.add(textoComandos);
        comandos.add(txtBarraComandos);

        /*adicionando painel comandos ao painel principal*/
        add(comandos, BorderLayout.SOUTH);

        /*adicionando eventos keylistener ao campo de texto txtBarraComandos,quando
        temos um txt field em uma janela acho que devemos adicionar um keylistener ao campo
        de texto e não a janela,assim as teclas disparando um keyevent quando apertamos um tecla
        no campo de texto*/
        txtBarraComandos.addKeyListener(this);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

// PINTANDO QUADRO DE DESENHO 1150PX POR 550 PX
        g.setColor(Color.BLACK);
        g.drawRect(20, 70, 1150, 550);
        //PINTANDO LINHAS QUADRO DE DESENHO

        g.setColor(new Color(50, 50, 50)); //cinza
        for (int i = 0; i < 25; i++) { // linhas verticais 50 PIXELS linhas de 550 pixels comprimento
            g.drawLine(50 + i * 50, 70, 50 + i * 50, 620); // coordenadas JPanel
        }
        for (int i = 0; i < 13; i++) {// linhas horizontais 50 PIXELS linhas de 1150 pixels comprimento
            g.drawLine(50, 70 + i * 50, 1200, 70 + i * 50); // coordenadas JPanel
        }

// DESENHANDO SISTEMA DE COORDENADAS
        g.setColor(Color.YELLOW);
        g.drawLine(50, 620, 100, 620); // eixo x // coordenadas JPanel
        g.drawString("x", 110, 625);
        g.drawLine(50, 620, 50, 570); // eixo y // coordenadas JPanel
        g.drawString("y", 50, 560);

//DESENHANDO LINHAS
        for (int i = 1; i < pontos.size(); i++) {
            if (linhasVisiveis.get(i - 1)) { // se a linha for configurada como visível desenha linha
                g.setColor(Color.WHITE);
                int x1 = pontos.get(i - 1).x;
                int y1 = pontos.get(i - 1).y;
                int x2 = pontos.get(i).x;
                int y2 = pontos.get(i).y;
                g.drawLine(x1, y1, x2, y2);
            }

        }

// DESENHANDO CIRCULOS
        if (clickFinal) {
            g.setColor(Color.RED);
            g.drawRect(xcentro - 2, ycentro - 2, 5, 5);
            g.drawLine(xcentro - 5, ycentro, xcentro + 5, ycentro);
            g.drawLine(xcentro, ycentro - 5, xcentro, ycentro + 5);
            for (int i = 0; i < circulos.size(); i++) {
                g.setColor(Color.RED);
                int xce = circulos.get(i).xcentro;
                int yce = circulos.get(i).ycentro;
                int xco = circulos.get(i).xcontorno;
                int yco = circulos.get(i).ycontorno;
                int diametro = circulos.get(i).diametro;
                int x = circulos.get(i).x;
                int y = circulos.get(i).y;
                g.drawRect(xce - 2, yce - 2, 5, 5);
               g.drawLine(xce - 5, yce, xce + 5, yce);
                g.drawLine(xce, yce - 5, xce, yce + 5);
                g.setColor(Color.GREEN);
                g.drawLine(xce, yce, xco, yco);
                g.setColor(Color.WHITE);
                g.drawOval(x, y, diametro, diametro);
                g.setColor(Color.BLUE);
 g.drawRect(x, y, diametro, diametro);
            }
        } else {
            for (int i = 0; i < circulos.size(); i++) {
                g.setColor(Color.RED);
                int xce = circulos.get(i).xcentro;
                int yce = circulos.get(i).ycentro;
                int xco = circulos.get(i).xcontorno;
                int yco = circulos.get(i).ycontorno;
                int diametro = circulos.get(i).diametro;
                int x = circulos.get(i).x;
                int y = circulos.get(i).y;
                g.drawRect(xce - 2, yce - 2, 5, 5);
g.drawLine(xce - 5, yce, xce + 5, yce);
                g.drawLine(xce, yce - 5, xce, yce + 5);
                g.setColor(Color.GREEN);
                g.drawLine(xce, yce, xco, yco);
                g.setColor(Color.WHITE);
                g.drawOval(x, y, diametro, diametro);
                g.setColor(Color.BLUE);
                g.drawRect(x, y, diametro, diametro);
            }
        }
// pinta marcador linha
        if(linhaAtivada && marcadorLinha==true){
            /*verifica se o último ponto final do marcador linha(x2,y2) está fora da área de desenho
            se estiver pinta de laranjado indicando que não podemos desenhar uma linha
            naquela area
            */
            if((this.x2>=50)&&(this.x2<=1200)&&(this.y2>=70)&&(this.y2<=620)){
                g.setColor(new Color(128,255,128));// verde claro       
            }else{
                g.setColor(new Color(255,128,128)); // vermelho claro
            }
            
            g.drawLine(this.x1, this.y1, this.x2, this.y2);
g.drawString(tamanhoLinha+"",localizacaoXMarcadorLinha,localizacaoYMarcadorLinha);
            g.drawString("<"+anguloGrausLinha+"º",localizacaoXMarcadorLinha,localizacaoYMarcadorLinha+15);
            
        }
        
        //}
    }

    public int[] converteCoordenadas(int x, int y) {

        x -= 20;
        y = y + 480 + (y - 70) * (-2);
        int[] coordenadas = {x, y};
        return coordenadas;

    }
public void editarMenu() {
        //criando barra menu e adicionando ao painel
        barraMenu = new JMenuBar();
        /*para adicionar uma barra de menus a um Painel usamos o método add
        especificando NORTH para o border Layout*/
        add(barraMenu, BorderLayout.NORTH);
        //criando menus e adicionando a barra de menus
        menuArquivo = new JMenu("Arquivo");
        barraMenu.add(menuArquivo);
        menuDesenhar = new JMenu("Desenhar");
        barraMenu.add(menuDesenhar);

        // criando itens do menu de Arquivo e adicionando ao menu e adicionando evento
        itemArquivoSair = new JMenuItem("Sair");
        menuArquivo.add(itemArquivoSair);
// criando itens do menu Desenhar adicionando eventos e adicionando ao menu
        itemDesenharLinha = new JMenuItem("Linha");
        itemDesenharCirculo = new JMenuItem("Círculo");

        menuDesenhar.add(itemDesenharLinha);
        menuDesenhar.add(itemDesenharCirculo);

        //TRATANDO EVENTOS DOS ITENS DE MENU
        itemArquivoSair.addActionListener(this);
        itemDesenharLinha.addActionListener(this);
        itemDesenharCirculo.addActionListener(this);

    }
@Override
    public void mouseDragged(MouseEvent e) {

        // reajustando cordenadas do jpanel e convertendo para a grade de coordenadas
        int x = e.getX(); // panel coordenada x JPanel
        int y = e.getY(); // panel coordenada y JPanel

        // Painel 1150 por 550
        // Panel  canto inferior esquerdo (50,620)
        // Panel  canto superior esquerdo(50,70)
        // Panel canto superior direito (1200,70)
        // Panel canto inferior direito(1200,620)

  // reajustando coordenadas do panel para o sistema de coordenadas x e y
        x = x - 50;
        //y=70+480; //550    se y=70
        //y=71+478; // 549   se y=71
        //y=72+476; // 548   se y=72
        y = y + 480 + (y - 70) * (-2); // lei geral
        // só exibe as coordenadas na área de desenho
        if ((x >= 0) && (x <= 1150) && (y >= 0) && (y <= 550)) {
            coordenadas.setText("[x:" + x + "]" + "[y:" + y + "]");
        } else {
            coordenadas.setText("Fora da área de desenho");
        }

    }

@Override
    public void mouseMoved(MouseEvent e) {
        // reajustando cordenadas do jpanel e 

convertendo para a grade de coordenadas
int x = e.getX(); // panel coordenada x
int y = e.getY(); // panel coordenada y

    // Painel 1150 por 550
    // Panel  canto inferior esquerdo (50,620)
    // Panel  canto superior esquerdo(50,70)
    // Panel canto superior direito (1200,70)
    // Panel canto inferior direito(1200,620)
    // reajustando coordenadas do panel
 para o sistema de coordenadas x e y
        x = x - 50;
        //y=70+480; //550    se y=70
        //y=71+478; // 549   se y=71
        //y=72+476; // 548   se y=72

y = y + 480 + (y - 70) * (-2); // lei geral
        // só exibe as coordenadas na área de desenho
        if ((x >= 0) && (x <= 1150) && (y >= 0) && (y <= 550)) {
            coordenadas.setText("[x:" + x + "]" + "[y:" + y + "]");
        } else {
            coordenadas.setText("Fora da área de desenho");
        }
        /*se proximo ponto for verdadeiro significa que já devemos o primeiro clique na nova
        linha e então podemos exibir o marcador linha*/
        if(proximoPonto){
            marcadorLinha=true;
        }
/*
        se a linha estiver ativada e proxima linha for verdadeira 
        reativa o marcador linha quando movimentamos o mouse*/
        
            
        
        
        if (linhaAtivada && pontos.size() > 0) { // garantir que o array list não é vazio
            this.x2 = e.getX();
            this.y2 = e.getY();
            this.x1 = pontos.get(pontos.size() - 1).x; // pega a coordenada x do último ponto da última linha
            this.y1 = pontos.get(pontos.size() - 1).y; // pega a coordenada y do último ponto da última linha
            double distanciaX=x2-x1;
            double distanciaY=-(y2-y1);   // inverter a distancia pois o eixo y conta de cima para baixo
double anguloRad=Math.atan(distanciaY/distanciaX);
            tamanhoLinha=Math.sqrt(Math.pow(x2-x1,2)+Math.pow(y2-y1,2));
           
            // inverter a desigualdade no eixo y pois o eixo y conta de cima para baixo y1>y2 vira y1<y1
            //1º quadrante
            if((x2>x1)&&(y2<y1)){
                anguloGrausLinha=(180*anguloRad)/Math.PI;
                
            }
            //2º quadrante
            if((x2<x1)&&(y2<y1)){
                anguloGrausLinha=180+(180*anguloRad)/Math.PI; // soma 180 graus pois o angulo é retornado no 4º pelo atan
            }
//3º quadrante 
            if((x2<x1)&&(y2>y1)){
                anguloGrausLinha=180+(180*anguloRad)/Math.PI; // soma 180 graus pois o angulo é retornado no 1º quadrante
            }
            //4º quadrante
            if((x2>x1)&&(y2>y1)){
                anguloGrausLinha=360+(180*anguloRad)/Math.PI;
            }
//eixo x positivo
            if((y1==y2)&&(x2>x1)){
                anguloGrausLinha=0;
            }
            // eixo x negativo
            if((y1==y2)&&(x2<x1)){
                anguloGrausLinha=180;
            }
            // eixo y positivo
            if((y2<y1)&&(x2==x1)){
                anguloGrausLinha=90;
            }
            // eixo y negativo
            if((y2>y1)&&(x2==x1)){
                anguloGrausLinha=270;
            }

localizacaoXMarcadorLinha=e.getX()+50;
            localizacaoYMarcadorLinha=e.getY()+50;
            repaint();
        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

@Override
    public void mousePressed(MouseEvent e) {
        if (linhaAtivada) {
            

            
            Point ponto = e.getPoint();
            // verifica se o ponto está na área de desenho e apenas adiciona o ponto se estiver na area de desenho
            if((ponto.x>=50)&&(ponto.x<=1200)&&(ponto.y>=70)&&(ponto.y<=620)){
                proximoPonto = true;
                if (proximoPonto) {
                    txtBarraComandos.setText("LINHA especifique o próximo ponto: ");
                }
                pontos.add(ponto);
                linhasVisiveis.add(true);
                indiceLinha++;// incrementa toda vez que um novo ponto é atribuido e um linha criada

// indice 0 para primeira linha
                marcadorLinha=false; // desativa o marcador linha quando clicarmos em um ponto
                repaint();
            }
           
        }
        if (circuloAtivado) {
            if (clickInicial) {

                xcentro = e.getX();
                ycentro = e.getY();

            } else {

                xcontorno = e.getX();
                ycontorno = e.getY();
                circulos.add(new Circulo(xcentro, ycentro, xcontorno, ycontorno));

            }

if (clickInicial == true) {
                clickInicial = false;
            } else {
                clickInicial = true;
            }
            if (clickFinal == false) {
                clickFinal = true;
            } else {
                clickFinal = false;
            }
        }
        repaint();

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

  @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == itemArquivoSair) {
            System.exit(0);
        }
        if (e.getSource() == itemDesenharLinha) {
            linhaAtivada = true;
            circuloAtivado = false;
            textoComandos.setText("LINHA ATIVADA");
            textoComandos.setForeground(Color.RED);
            txtBarraComandos.setText("LINHA especifique o primeiro ponto: ");

marcadorLinha=false;
            proximoPonto=false; // volta variável proximoPonto para false quando a linha for desativada
            if (indiceLinha >= 0) {
                linhasVisiveis.set(indiceLinha, false);
                System.out.println("Comando linha desativado");
                System.out.println("Pressione L e a tecla ENTER para ativar o comando linha");
            }
        }
    }

@Override
    public void keyTyped(KeyEvent e) {

    }

@Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
            /*o operador igual não serve para compararmos se duas Strings são 
            iguais temos que usar o método equals ou equalIgnoreToCase para isso 
            O método equals da classe String compara se uma String passada entre parênteses
            é igual a String que está sendo usada para acessar o método equals,esse método
            método considera as diferenças entre letras maiusculas e letra minúsculas ou seja
            a String "MARIA" será considerada diferente da String "maria" e o método retorna 
            true se as Strings forem iguais e retorna false se as Strings são diferentes
            equalsIgnoreCase(String s) – igual ao equals,
            porém ignora MAIÚSCULAS e minúsculas. Retorna
            true ou false (boolean).*/

/*no nosso caso iremos passar como parâmetro para equalsIgnoreCase o retorno 
            da barra de comandos e eremos comparar com a String que está acessando o método
            no caso a String "C"*/
            if (("L".equalsIgnoreCase(txtBarraComandos.getText())) || ("LINHA".equalsIgnoreCase(txtBarraComandos.getText()))) {
                linhaAtivada = true;
                circuloAtivado = false;
                textoComandos.setText("LINHA ATIVADA");
                textoComandos.setForeground(Color.RED);
                txtBarraComandos.setText("LINHA especifique o primeiro ponto: ");
                marcadorLinha=false;// matém o marcador linha em false para ativar só quando clicar
            }

if (("C".equalsIgnoreCase(txtBarraComandos.getText())) || ("CÍRCULO".equalsIgnoreCase(txtBarraComandos.getText()))) {
                circuloAtivado = true;
                linhaAtivada = false;
                textoComandos.setText("CÍRCULO ATIVADO");
                textoComandos.setForeground(Color.RED);
                txtBarraComandos.setText("LINHA especifique o primeiro ponto: ");
                marcadorLinha=false;
                
                
            }

}

if (e.getKeyCode() == 27) { // tecla ESC
            linhaAtivada = false;
            circuloAtivado = false;
            /*muda o índice atual da linha onde esc foi pressionado e muda para 
                    false*/

 /*o método set de um arraylist substitui o elemento na posição especificada
                    nesta lista pelo elemento especificado,o primeiro valor é o indice do elemento
                    que será substituído,o segundo valor é o novo elemento que será substituído,
                    neste caso iremos passar false para o array list já que está empacotado
                    num wrapper*/

if (indiceLinha >= 0) {
                linhasVisiveis.set(indiceLinha, false);
            }
            txtBarraComandos.setText("");
            textoComandos.setText("nenhum comando encontrado");
            textoComandos.setForeground(Color.BLACK);
            proximoPonto=false; // volta o proximoPonto para false quando a linha for desativada
            marcadorLinha=false;
            repaint();

        }
    }

@Override
    public void keyReleased(KeyEvent e) {

    }

DesenhoTeste.java

package miniCad4;

import java.awt.event.KeyEvent;

import java.awt.event.KeyListener;
import javax.swing.JFrame;

public class DesenhoTeste {
    
    public static void main(String[] args) {
        
        JFrame janela = new JFrame("MiniCAD");
        Desenho desenho = new Desenho();
        janela.setSize(1260, 720); // 1200 700
        janela.setVisible(true);
        janela.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        janela.setLocationRelativeTo(null);
        janela.setResizable(false);
        janela.add(desenho);
        
       // System.out.println(Math.atan(1));
        
    }
    
}

Circulo.java

package miniCad4;

public class Circulo {


    double raio;
    int x;
    int y;
    int diametro;
    int xcentro;
    int ycentro;
    int xcontorno;
    int ycontorno;

    public Circulo(int xcentro, int ycentro, int xcontorno, int ycontorno) {
        this.xcentro = xcentro;
        this.ycentro = ycentro;
        this.xcontorno = xcontorno;
        this.ycontorno = ycontorno;

        raio = Math.sqrt(Math.pow((xcentro - xcontorno), 2) + Math.pow((ycentro - ycontorno), 2));
        /*Devemos arredondar o valor e fazer um cast para um inteiro pois draw oval só aceita
        inteiros*/
        x = (int) Math.round(xcentro - raio);
        y = (int) Math.round(ycentro - raio);
        diametro = (int) Math.round(2 * raio);

} 
}