commit 5e9828b53ef4ca04bfb196f774971d5bf5a68c55 Author: Clinv Date: Tue Nov 3 21:10:04 2026 -0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..5d5ae49 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +cmake_minimum_required(VERSION 3.20) + +project(LinBAT VERSION 0.1.0 LANGUAGES NONE) + +find_package(Java 17 REQUIRED COMPONENTS Runtime Development) + +add_subdirectory(app) diff --git a/README.md b/README.md new file mode 100644 index 0000000..b1c9128 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# LinBAT + +LinBAT es una aplicación para Linux que permite comprimir y +descomprimir archivos mediante su propio formato `.lbt`. + +## Estado del proyecto + +Actualmente se encuentra en desarrollo. + +La interfaz gráfica está en construcción. El motor de compresión +y extracción todavía no está implementado. + +## Tecnologías + +- Java 17 o superior +- Java Swing +- CMake +- C++ para el futuro motor de compresión + +## Compilación y ejecución + +Desde la carpeta raíz del proyecto: + +```bash +cmake -S . -B build +cmake --build build --target linbat diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..6f62ef5 --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,33 @@ +set(LINBAT_JAVA_SOURCE_DIR + "${PROJECT_SOURCE_DIR}/ui/src" +) + +set(LINBAT_JAVA_OUTPUT_DIR + "${PROJECT_BINARY_DIR}/classes" +) + +file(GLOB JAVA_SOURCES CONFIGURE_DEPENDS + "${LINBAT_JAVA_SOURCE_DIR}/*.java" +) + +if(NOT JAVA_SOURCES) + message(FATAL_ERROR "No se encontraron archivos Java en ui/src") +endif() + +add_custom_target(linbat + COMMAND "${CMAKE_COMMAND}" -E make_directory + "${LINBAT_JAVA_OUTPUT_DIR}" + + COMMAND "${Java_JAVAC_EXECUTABLE}" + -encoding UTF-8 + -d "${LINBAT_JAVA_OUTPUT_DIR}" + ${JAVA_SOURCES} + + COMMAND "${Java_JAVA_EXECUTABLE}" + -cp "${LINBAT_JAVA_OUTPUT_DIR}" + Main + + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + SOURCES ${JAVA_SOURCES} + VERBATIM +) diff --git a/docs/interfaz.md b/docs/interfaz.md new file mode 100644 index 0000000..771d706 --- /dev/null +++ b/docs/interfaz.md @@ -0,0 +1,38 @@ +# Interfaz gráfica de LinBAT + +## Estado + +La interfaz gráfica se encuentra en desarrollo. + +## Ventana principal + +La aplicación dispone de dos pestañas: + +- Comprimir +- Extraer + +## Compresión + +Permite seleccionar archivos y carpetas, configurar el nombre +del archivo de salida y elegir el nivel de compresión. + +La compresión real todavía no está implementada. + +## Extracción + +Permite seleccionar un archivo `.lbt`. + +La extracción real todavía no está implementada. + +## Tecnologías + +- Java 17 +- Swing +- CMake + +## Próximos pasos + +1. Completar el diseño visual. +2. Añadir la selección de carpeta de destino. +3. Añadir una barra de progreso. +4. Conectar la interfaz con el motor C++. diff --git a/ui/src/FileSelectionPanel.java b/ui/src/FileSelectionPanel.java new file mode 100644 index 0000000..19f580c --- /dev/null +++ b/ui/src/FileSelectionPanel.java @@ -0,0 +1,159 @@ +import javax.swing.*; +import java.awt.*; +import java.io.File; +import java.util.List; + +public final class FileSelectionPanel extends JPanel { + + private final DefaultListModel fileModel; + private final JList fileList; + + public FileSelectionPanel() { + super(new BorderLayout(8, 8)); + + fileModel = new DefaultListModel<>(); + fileList = new JList<>(fileModel); + + fileList.setCellRenderer((list, file, index, selected, focus) -> { + String name = file.getName(); + + if (name.isEmpty()) { + name = file.getAbsolutePath(); + } + + JLabel label = new JLabel( + name + " — " + getFileSize(file) + ); + + label.setOpaque(true); + label.setBorder( + BorderFactory.createEmptyBorder(6, 8, 6, 8) + ); + + if (selected) { + label.setBackground(list.getSelectionBackground()); + label.setForeground(list.getSelectionForeground()); + } else { + label.setBackground(list.getBackground()); + label.setForeground(list.getForeground()); + } + + return label; + }); + + JButton addFilesButton = new JButton("Añadir archivos"); + JButton addFolderButton = new JButton("Añadir carpeta"); + JButton removeButton = new JButton("Quitar selección"); + + addFilesButton.addActionListener(event -> selectFiles()); + addFolderButton.addActionListener(event -> selectFolder()); + removeButton.addActionListener(event -> removeSelectedFiles()); + + JPanel buttons = new JPanel( + new FlowLayout(FlowLayout.LEFT) + ); + + buttons.add(addFilesButton); + buttons.add(addFolderButton); + buttons.add(removeButton); + + add(buttons, BorderLayout.NORTH); + add(new JScrollPane(fileList), BorderLayout.CENTER); + } + + private void selectFiles() { + JFileChooser chooser = new JFileChooser(); + + chooser.setMultiSelectionEnabled(true); + chooser.setFileSelectionMode( + JFileChooser.FILES_ONLY + ); + + int result = chooser.showOpenDialog(this); + + if (result == JFileChooser.APPROVE_OPTION) { + for (File file : chooser.getSelectedFiles()) { + addFile(file); + } + } + } + + private void selectFolder() { + JFileChooser chooser = new JFileChooser(); + + chooser.setFileSelectionMode( + JFileChooser.DIRECTORIES_ONLY + ); + + int result = chooser.showOpenDialog(this); + + if (result == JFileChooser.APPROVE_OPTION) { + addFile(chooser.getSelectedFile()); + } + } + + private void addFile(File file) { + if (!file.exists()) { + return; + } + + for (int i = 0; i < fileModel.size(); i++) { + if (fileModel.get(i).equals(file)) { + return; + } + } + + if (file.getName().toLowerCase().endsWith(".lbt")) { + JOptionPane.showMessageDialog( + this, + "No se pueden añadir archivos .lbt para comprimir.", + "Archivo no permitido", + JOptionPane.WARNING_MESSAGE + ); + + return; + } + + fileModel.addElement(file); + } + + private void removeSelectedFiles() { + List selectedFiles = fileList.getSelectedValuesList(); + + for (File file : selectedFiles) { + fileModel.removeElement(file); + } + } + + private String getFileSize(File file) { + if (file.isDirectory()) { + return "Carpeta"; + } + + long bytes = file.length(); + + if (bytes < 1024) { + return bytes + " B"; + } + + if (bytes < 1024 * 1024) { + return String.format("%.1f KB", bytes / 1024.0); + } + + if (bytes < 1024L * 1024 * 1024) { + return String.format( + "%.1f MB", + bytes / (1024.0 * 1024.0) + ); + } + + return String.format( + "%.2f GB", + bytes / (1024.0 * 1024.0 * 1024.0) + ); + } + + public List getSelectedFiles() { + return fileList.getSelectedValuesList(); + } +} diff --git a/ui/src/Main.java b/ui/src/Main.java new file mode 100644 index 0000000..3927eca --- /dev/null +++ b/ui/src/Main.java @@ -0,0 +1,25 @@ +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public final class Main { + + private Main() { + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(() -> { + try { + UIManager.setLookAndFeel( + UIManager.getSystemLookAndFeelClassName() + ); + } catch (Exception exception) { + System.err.println( + "No se pudo cargar el tema del sistema." + ); + } + + MainWindow window = new MainWindow(); + window.setVisible(true); + }); + } +} diff --git a/ui/src/MainWindow.java b/ui/src/MainWindow.java new file mode 100644 index 0000000..8b94666 --- /dev/null +++ b/ui/src/MainWindow.java @@ -0,0 +1,158 @@ +import javax.swing.*; +import java.awt.*; + +public final class MainWindow extends JFrame { + + private final FileSelectionPanel fileSelectionPanel; + + public MainWindow() { + super("LinBAT"); + + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + setMinimumSize(new Dimension(720, 480)); + setSize(900, 600); + setLocationRelativeTo(null); + + fileSelectionPanel = new FileSelectionPanel(); + + JTabbedPane tabs = new JTabbedPane(); + tabs.addTab("Comprimir", createCompressionPanel()); + tabs.addTab("Extraer", createExtractionPanel()); + + add(tabs, BorderLayout.CENTER); + } + + private JPanel createCompressionPanel() { + JPanel panel = new JPanel(new BorderLayout(12, 12)); + panel.setBorder( + BorderFactory.createEmptyBorder(16, 16, 16, 16) + ); + + JLabel title = new JLabel("Crear archivo .lbt"); + title.setFont(title.getFont().deriveFont(Font.BOLD, 20f)); + + JLabel description = new JLabel( + "Selecciona los archivos o carpetas que deseas comprimir." + ); + + JPanel header = new JPanel(new BorderLayout(4, 4)); + header.add(title, BorderLayout.NORTH); + header.add(description, BorderLayout.SOUTH); + + JPanel options = new JPanel(new GridBagLayout()); + GridBagConstraints constraints = new GridBagConstraints(); + + constraints.insets = new Insets(4, 4, 4, 12); + constraints.anchor = GridBagConstraints.WEST; + + constraints.gridx = 0; + constraints.gridy = 0; + options.add(new JLabel("Nombre del archivo:"), constraints); + + JTextField outputName = new JTextField("archivo.lbt", 24); + + constraints.gridx = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 1; + options.add(outputName, constraints); + + constraints.gridx = 0; + constraints.gridy = 1; + constraints.fill = GridBagConstraints.NONE; + constraints.weightx = 0; + options.add(new JLabel("Nivel de compresión:"), constraints); + + JComboBox compressionLevel = new JComboBox<>( + new String[]{"Rápida", "Normal", "Alta"} + ); + + constraints.gridx = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + constraints.weightx = 1; + options.add(compressionLevel, constraints); + + JButton compressButton = new JButton("Comprimir"); + + compressButton.addActionListener(event -> { + JOptionPane.showMessageDialog( + this, + "La compresión todavía no está implementada.", + "LinBAT", + JOptionPane.INFORMATION_MESSAGE + ); + }); + + JPanel footer = new JPanel( + new FlowLayout(FlowLayout.RIGHT) + ); + footer.add(compressButton); + + JPanel bottom = new JPanel(new BorderLayout(8, 8)); + bottom.add(options, BorderLayout.CENTER); + bottom.add(footer, BorderLayout.SOUTH); + + panel.add(header, BorderLayout.NORTH); + panel.add(fileSelectionPanel, BorderLayout.CENTER); + panel.add(bottom, BorderLayout.SOUTH); + + return panel; + } + + private JPanel createExtractionPanel() { + JPanel panel = new JPanel(new BorderLayout(12, 12)); + panel.setBorder( + BorderFactory.createEmptyBorder(16, 16, 16, 16) + ); + + JLabel title = new JLabel("Extraer archivo .lbt"); + title.setFont(title.getFont().deriveFont(Font.BOLD, 20f)); + + JLabel description = new JLabel( + "Selecciona un archivo LinBAT para preparar su extracción." + ); + + JButton selectButton = new JButton("Seleccionar archivo .lbt"); + JLabel selectedFile = new JLabel("Ningún archivo seleccionado"); + + selectButton.addActionListener(event -> { + JFileChooser chooser = new JFileChooser(); + + chooser.setFileFilter( + new javax.swing.filechooser.FileNameExtensionFilter( + "Archivos LinBAT (*.lbt)", + "lbt" + ) + ); + + int result = chooser.showOpenDialog(this); + + if (result == JFileChooser.APPROVE_OPTION) { + selectedFile.setText( + chooser.getSelectedFile().getAbsolutePath() + ); + } + }); + + JButton extractButton = new JButton("Extraer"); + + extractButton.addActionListener(event -> { + JOptionPane.showMessageDialog( + this, + "La extracción todavía no está implementada.", + "LinBAT", + JOptionPane.INFORMATION_MESSAGE + ); + }); + + JPanel selection = new JPanel(new BorderLayout(8, 8)); + selection.add(selectButton, BorderLayout.NORTH); + selection.add(selectedFile, BorderLayout.CENTER); + selection.add(extractButton, BorderLayout.SOUTH); + + panel.add(title, BorderLayout.NORTH); + panel.add(description, BorderLayout.CENTER); + panel.add(selection, BorderLayout.SOUTH); + + return panel; + } +}