commit 6db103cd042a51833b21344c98cd1d62ad282c31 Author: 230404 <230404@epvc.pt> Date: Wed Mar 25 21:00:01 2026 +0000 first commit diff --git a/Awesome_API/.vscode/settings.json b/Awesome_API/.vscode/settings.json new file mode 100644 index 0000000..e112a70 --- /dev/null +++ b/Awesome_API/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "java.project.sourcePaths": ["src"], + "java.project.outputPath": "bin", + "java.project.referencedLibraries": [ + "lib/**/*.jar" + ] +} diff --git a/Awesome_API/README.md b/Awesome_API/README.md new file mode 100644 index 0000000..7c03a53 --- /dev/null +++ b/Awesome_API/README.md @@ -0,0 +1,18 @@ +## Getting Started + +Welcome to the VS Code Java world. Here is a guideline to help you get started to write Java code in Visual Studio Code. + +## Folder Structure + +The workspace contains two folders by default, where: + +- `src`: the folder to maintain sources +- `lib`: the folder to maintain dependencies + +Meanwhile, the compiled output files will be generated in the `bin` folder by default. + +> If you want to customize the folder structure, open `.vscode/settings.json` and update the related settings there. + +## Dependency Management + +The `JAVA PROJECTS` view allows you to manage your dependencies. More details can be found [here](https://github.com/microsoft/vscode-java-dependency#manage-dependencies). diff --git a/Awesome_API/bin/Main$1.class b/Awesome_API/bin/Main$1.class new file mode 100644 index 0000000..e02b54b Binary files /dev/null and b/Awesome_API/bin/Main$1.class differ diff --git a/Awesome_API/bin/Main$2.class b/Awesome_API/bin/Main$2.class new file mode 100644 index 0000000..352c6bc Binary files /dev/null and b/Awesome_API/bin/Main$2.class differ diff --git a/Awesome_API/bin/Main.class b/Awesome_API/bin/Main.class new file mode 100644 index 0000000..12e90d4 Binary files /dev/null and b/Awesome_API/bin/Main.class differ diff --git a/Awesome_API/src/Main.java b/Awesome_API/src/Main.java new file mode 100644 index 0000000..c72ee59 --- /dev/null +++ b/Awesome_API/src/Main.java @@ -0,0 +1,334 @@ +import java.awt.*; +import java.awt.event.*; +import java.io.*; +import java.net.*; +import java.util.regex.*; +import javax.swing.*; +import javax.swing.border.EmptyBorder; + +public class Main extends JFrame { + + // Cores do Design Moderno + private static final Color COLOR_BG_TOP = new Color(138, 180, 248); + private static final Color COLOR_BG_BOTTOM = new Color(25, 103, 210); + private static final Color COLOR_CARD = new Color(255, 255, 255, 220); + private static final Color COLOR_BTN_PRIMARY = new Color(242, 186, 45); + private static final Color COLOR_BTN_SECONDARY = new Color(219, 68, 55); + + // Dados limpos + private String[] moedaDisplay = { + "Dólar Americano (USD)", "Euro (EUR)", "Real Brasileiro (BRL)", + "Libra Esterlina (GBP)", "Iene Japonês (JPY)", "Dólar Canadense (CAD)", + "Dólar Australiano (AUD)", "Franco Suíço (CHF)" + }; + private String[] moedaAbrev = {"USD", "EUR", "BRL", "GBP", "JPY", "CAD", "AUD", "CHF"}; + + private JComboBox cmbFrom; + private JComboBox cmbTo; + private JTextField txtValue; + private JLabel lblResult; + private JLabel lblResultSub; + + // Texto de Exemplo (Placeholder) + private final String PLACEHOLDER_TEXT = "Ex: 100.00"; + + public Main() { + setTitle("Conversor de Moedas"); + setSize(420, 750); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setLocationRelativeTo(null); + + // Painel Principal com Gradiente Azul + JPanel mainPanel = new JPanel() { + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GradientPaint gp = new GradientPaint(0, 0, COLOR_BG_TOP, 0, getHeight(), COLOR_BG_BOTTOM); + g2.setPaint(gp); + g2.fillRect(0, 0, getWidth(), getHeight()); + g2.dispose(); + } + }; + mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); + mainPanel.setBorder(new EmptyBorder(20, 20, 20, 20)); + setContentPane(mainPanel); + + // --- TÍTULO --- + JLabel title = new JLabel("Conversor de Moedas", SwingConstants.CENTER); + title.setFont(new Font("Segoe UI", Font.BOLD, 30)); + title.setForeground(Color.WHITE); + title.setAlignmentX(Component.CENTER_ALIGNMENT); + mainPanel.add(title); + mainPanel.add(Box.createVerticalStrut(20)); + + // --- CARTÃO 1: SELEÇÃO DE MOEDAS --- + RoundedPanel cardMoedas = new RoundedPanel(); + cardMoedas.setLayout(new BoxLayout(cardMoedas, BoxLayout.Y_AXIS)); + + JLabel lblDe = new JLabel("Converter De:"); + lblDe.setFont(new Font("Segoe UI", Font.PLAIN, 14)); + lblDe.setForeground(Color.DARK_GRAY); + + cmbFrom = new JComboBox<>(moedaDisplay); + styleComboBox(cmbFrom); + + JLabel lblPara = new JLabel("Para:"); + lblPara.setFont(new Font("Segoe UI", Font.PLAIN, 14)); + lblPara.setForeground(Color.DARK_GRAY); + + cmbTo = new JComboBox<>(moedaDisplay); + styleComboBox(cmbTo); + cmbTo.setSelectedIndex(2); // Padrão BRL + + JPanel pnlDe = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlDe.setOpaque(false); pnlDe.add(lblDe); + JPanel pnlPara = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlPara.setOpaque(false); pnlPara.add(lblPara); + + cardMoedas.add(pnlDe); + cardMoedas.add(cmbFrom); + cardMoedas.add(Box.createVerticalStrut(15)); + cardMoedas.add(pnlPara); + cardMoedas.add(cmbTo); + + mainPanel.add(cardMoedas); + mainPanel.add(Box.createVerticalStrut(15)); + + // --- CARTÃO 2: QUANTIDADE COM PLACEHOLDER --- + RoundedPanel cardValor = new RoundedPanel(); + cardValor.setLayout(new BoxLayout(cardValor, BoxLayout.Y_AXIS)); + + JLabel lblVal = new JLabel("Quantidade a Converter:"); + lblVal.setFont(new Font("Segoe UI", Font.PLAIN, 14)); + lblVal.setForeground(Color.DARK_GRAY); + JPanel pnlVal = new JPanel(new FlowLayout(FlowLayout.LEFT)); pnlVal.setOpaque(false); pnlVal.add(lblVal); + + // Configuração do Placeholder + txtValue = new JTextField(PLACEHOLDER_TEXT); + txtValue.setForeground(Color.GRAY); // Cor de texto fantasma + styleTextField(txtValue); + + // Evento para limpar o placeholder quando se clica + txtValue.addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + if (txtValue.getText().equals(PLACEHOLDER_TEXT)) { + txtValue.setText(""); + txtValue.setForeground(Color.BLACK); // Volta à cor normal para o user escrever + } + } + + @Override + public void focusLost(FocusEvent e) { + if (txtValue.getText().isEmpty()) { + txtValue.setForeground(Color.GRAY); + txtValue.setText(PLACEHOLDER_TEXT); // Volta o texto fantasma se não escreverem nada + } + } + }); + + cardValor.add(pnlVal); + cardValor.add(txtValue); + mainPanel.add(cardValor); + mainPanel.add(Box.createVerticalStrut(20)); + + // --- BOTÕES PRINCIPAIS --- + JButton btnConvert = new RoundedButton("Converter Agora", COLOR_BTN_PRIMARY, Color.BLACK); + mainPanel.add(btnConvert); + mainPanel.add(Box.createVerticalStrut(10)); + + JButton btnInvert = new RoundedButton("🔁 Inverter Moedas", COLOR_BTN_SECONDARY, Color.WHITE); + btnInvert.addActionListener(e -> inverterMoedas()); + mainPanel.add(btnInvert); + mainPanel.add(Box.createVerticalStrut(20)); + + // --- CARTÃO 3: RESULTADO --- + RoundedPanel cardResult = new RoundedPanel(); + cardResult.setLayout(new BoxLayout(cardResult, BoxLayout.Y_AXIS)); + + JLabel lblRecebera = new JLabel("Você receberá:"); + lblRecebera.setFont(new Font("Segoe UI", Font.PLAIN, 14)); + lblRecebera.setForeground(Color.DARK_GRAY); + lblRecebera.setAlignmentX(Component.CENTER_ALIGNMENT); + + lblResult = new JLabel("0.00", SwingConstants.CENTER); + lblResult.setFont(new Font("Segoe UI", Font.BOLD, 42)); + lblResult.setForeground(new Color(20, 20, 20)); + lblResult.setAlignmentX(Component.CENTER_ALIGNMENT); + + lblResultSub = new JLabel("-"); + lblResultSub.setFont(new Font("Segoe UI", Font.PLAIN, 16)); + lblResultSub.setForeground(Color.DARK_GRAY); + lblResultSub.setAlignmentX(Component.CENTER_ALIGNMENT); + + cardResult.add(Box.createVerticalStrut(10)); + cardResult.add(lblRecebera); + cardResult.add(Box.createVerticalStrut(10)); + cardResult.add(lblResult); + cardResult.add(lblResultSub); + cardResult.add(Box.createVerticalStrut(10)); + + mainPanel.add(cardResult); + + // --- LÓGICA DO BOTÃO CONVERTER --- + btnConvert.addActionListener(e -> { + int indexFrom = cmbFrom.getSelectedIndex(); + int indexTo = cmbTo.getSelectedIndex(); + + String input = txtValue.getText().replace(",", "."); + + // Verifica se o utilizador não escreveu nada e deixou o placeholder lá + if (input.equals(PLACEHOLDER_TEXT) || input.isEmpty()) { + JOptionPane.showMessageDialog(this, "Insere um número válido, senão vai dar merda!", "Erro", JOptionPane.ERROR_MESSAGE); + return; + } + + final double val; + try { + val = Double.parseDouble(input); + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(this, "Apenas números, por favor. Senão vai dar merda!", "Erro", JOptionPane.ERROR_MESSAGE); + return; + } + + if (indexFrom == indexTo) { + lblResult.setText(String.format("%.2f %s", val, moedaAbrev[indexTo])); + lblResultSub.setText(moedaDisplay[indexTo]); + return; + } + + lblResult.setText("A calcular..."); + + new Thread(() -> { + try { + String m1 = moedaAbrev[indexFrom]; + String m2 = moedaAbrev[indexTo]; + double rate = obterTaxaDeCambio(m1, m2); + double finalValue = val * rate; + + SwingUtilities.invokeLater(() -> { + lblResult.setText(String.format("%.2f %s", finalValue, m2)); + lblResultSub.setText(moedaDisplay[indexTo]); + }); + + } catch (Exception ex) { + SwingUtilities.invokeLater(() -> { + lblResult.setText("Erro"); + JOptionPane.showMessageDialog(this, "Erro de rede: " + ex.getMessage(), "Erro", JOptionPane.ERROR_MESSAGE); + }); + } + }).start(); + }); + + // Foca o ecrã para o placeholder funcionar logo na primeira vez + getContentPane().requestFocusInWindow(); + } + + private void inverterMoedas() { + int indexFrom = cmbFrom.getSelectedIndex(); + int indexTo = cmbTo.getSelectedIndex(); + cmbFrom.setSelectedIndex(indexTo); + cmbTo.setSelectedIndex(indexFrom); + } + + private static double obterTaxaDeCambio(String m1, String m2) throws Exception { + String urlStr = "https://economia.awesomeapi.com.br/json/last/" + m1 + "-" + m2; + URL url = new URL(urlStr); + HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + conn.setRequestMethod("GET"); + conn.setConnectTimeout(5000); + conn.setReadTimeout(5000); + + if (conn.getResponseCode() != 200) throw new IOException("HTTP Error: " + conn.getResponseCode()); + + BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())); + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) response.append(line); + reader.close(); + + Pattern pattern = Pattern.compile("\"bid\"\\s*:\\s*\"([^\"]+)\""); + Matcher matcher = pattern.matcher(response.toString()); + if (matcher.find()) return Double.parseDouble(matcher.group(1)); + else throw new Exception("Chave 'bid' não encontrada."); + } + + // --- CLASSES DE ESTILO CUSTOMIZADAS --- + + // Painel Arredondado + class RoundedPanel extends JPanel { + public RoundedPanel() { + setOpaque(false); + setBorder(new EmptyBorder(15, 20, 15, 20)); + setMaximumSize(new Dimension(360, 200)); + } + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(new Color(0, 0, 0, 20)); + g2.fillRoundRect(2, 2, getWidth() - 4, getHeight() - 4, 25, 25); + g2.setColor(COLOR_CARD); + g2.fillRoundRect(0, 0, getWidth() - 4, getHeight() - 4, 25, 25); + g2.dispose(); + super.paintComponent(g); + } + } + + // Botão Arredondado + class RoundedButton extends JButton { + private Color bgColor; + public RoundedButton(String text, Color bg, Color fg) { + super(text); + this.bgColor = bg; + setForeground(fg); + setFont(new Font("Segoe UI", Font.BOLD, 18)); + setFocusPainted(false); + setContentAreaFilled(false); + setBorderPainted(false); + setAlignmentX(Component.CENTER_ALIGNMENT); + setMaximumSize(new Dimension(360, 50)); + setCursor(new Cursor(Cursor.HAND_CURSOR)); + + addMouseListener(new MouseAdapter() { + public void mouseEntered(MouseEvent e) { bgColor = bg.brighter(); repaint(); } + public void mouseExited(MouseEvent e) { bgColor = bg; repaint(); } + }); + } + @Override + protected void paintComponent(Graphics g) { + Graphics2D g2 = (Graphics2D) g.create(); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(new Color(0, 0, 0, 30)); + g2.fillRoundRect(2, 4, getWidth() - 4, getHeight() - 4, 20, 20); + g2.setColor(bgColor); + g2.fillRoundRect(0, 0, getWidth() - 4, getHeight() - 5, 20, 20); + g2.dispose(); + super.paintComponent(g); + } + } + + private void styleComboBox(JComboBox cb) { + cb.setMaximumSize(new Dimension(320, 40)); + cb.setFont(new Font("Segoe UI", Font.PLAIN, 16)); + cb.setBackground(Color.WHITE); + cb.setFocusable(false); + cb.setAlignmentX(Component.CENTER_ALIGNMENT); + } + + private void styleTextField(JTextField tf) { + tf.setMaximumSize(new Dimension(320, 45)); + tf.setFont(new Font("Segoe UI", Font.PLAIN, 18)); + tf.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createLineBorder(Color.LIGHT_GRAY, 1, true), + new EmptyBorder(5, 10, 5, 10) + )); + tf.setAlignmentX(Component.CENTER_ALIGNMENT); + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + new Main().setVisible(true); + }); + } +} \ No newline at end of file