From 0c2fb24711f12a3863877c2d65d1548da0e0ab53 Mon Sep 17 00:00:00 2001 From: Horfee Date: Thu, 2 Mar 2023 13:44:34 +0100 Subject: [PATCH 01/21] Fix for device not detected on MacOS --- driver/src/main/java/studio/driver/fs/DeviceUtils.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/driver/src/main/java/studio/driver/fs/DeviceUtils.java b/driver/src/main/java/studio/driver/fs/DeviceUtils.java index 70930816b..6d1c11d55 100644 --- a/driver/src/main/java/studio/driver/fs/DeviceUtils.java +++ b/driver/src/main/java/studio/driver/fs/DeviceUtils.java @@ -32,9 +32,9 @@ public static List listMountPoints() { .map(root -> root.toPath().toString()) .collect(Collectors.toList()); } else { - final String CMD_DF = "df -l"; - final Pattern dfPattern = Pattern.compile("^(\\/[^ ]+)[^/]+(/.*)$"); - + final String[] CMD_DF = new String[] {"/bin/sh", "-c", "df | tail -n +2"}; + final Pattern dfPattern = Pattern.compile("^([a-zA-Z:-]*\\/[^ ]+)[^/]+(\\/.*)$"); + List mountPoints = new ArrayList<>(); Process dfProcess = null; @@ -51,7 +51,7 @@ public static List listMountPoints() { if (matcher.matches()) { final String dev = matcher.group(1); final String rootPath = matcher.group(2); - if (dev.startsWith("/dev/")) { + if (dev.contains("/")) { mountPoints.add(rootPath); } } From 833e19fcd3b20d246e3c970717a0725305cdb5b2 Mon Sep 17 00:00:00 2001 From: Horfee Date: Thu, 2 Mar 2023 14:04:59 +0100 Subject: [PATCH 02/21] Fix for devices not listed --- driver/src/main/java/studio/driver/fs/DeviceUtils.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/driver/src/main/java/studio/driver/fs/DeviceUtils.java b/driver/src/main/java/studio/driver/fs/DeviceUtils.java index 6d1c11d55..3d58027f7 100644 --- a/driver/src/main/java/studio/driver/fs/DeviceUtils.java +++ b/driver/src/main/java/studio/driver/fs/DeviceUtils.java @@ -32,7 +32,8 @@ public static List listMountPoints() { .map(root -> root.toPath().toString()) .collect(Collectors.toList()); } else { - final String[] CMD_DF = new String[] {"/bin/sh", "-c", "df | tail -n +2"}; + final String[] CMD_DF = + SystemUtils.IS_OS_MAC ? new String[] {"/bin/sh", "-c", "df | tail -n +2"} : new String[] {"df", "-l"}; final Pattern dfPattern = Pattern.compile("^([a-zA-Z:-]*\\/[^ ]+)[^/]+(\\/.*)$"); List mountPoints = new ArrayList<>(); @@ -51,7 +52,7 @@ public static List listMountPoints() { if (matcher.matches()) { final String dev = matcher.group(1); final String rootPath = matcher.group(2); - if (dev.contains("/")) { + if (dev.startsWith("/dev/") || SystemUtils.IS_OS_MAC) { mountPoints.add(rootPath); } } From eb50344c565176de05745daf3719cc12ea1416f0 Mon Sep 17 00:00:00 2001 From: Horfee Date: Thu, 16 Mar 2023 22:44:30 +0100 Subject: [PATCH 03/21] Adding Studio desktop project --- pom.xml | 1 + studio-desktop/pom.xml | 164 +++ studio-desktop/src/main/assembly/dist.xml | 42 + studio-desktop/src/main/java/studio/GUI.java | 1127 +++++++++++++++++ .../src/main/java/studio/JsonPackCell.java | 187 +++ .../main/java/studio/database/JsonPack.java | 125 ++ .../main/java/studio/database/Library.java | 241 ++++ .../java/studio/database/LocalizedInfos.java | 76 ++ .../src/main/java/studio/database/Person.java | 43 + .../java/studio/database/Thumbnailable.java | 45 + .../localization/Translation.properties | 21 + .../localization/Translation_fr_FR.properties | 21 + .../src/main/resources/META-INF/MANIFEST.MF | 6 + studio-desktop/src/main/resources/log4j2.xml | 47 + .../src/main/resources/logolunii.jpeg | Bin 0 -> 70565 bytes studio-desktop/src/main/resources/lunii.png | Bin 0 -> 255552 bytes studio-desktop/src/main/resources/studio.bat | 7 + studio-desktop/src/main/resources/studio.sh | 7 + 18 files changed, 2160 insertions(+) create mode 100644 studio-desktop/pom.xml create mode 100644 studio-desktop/src/main/assembly/dist.xml create mode 100644 studio-desktop/src/main/java/studio/GUI.java create mode 100644 studio-desktop/src/main/java/studio/JsonPackCell.java create mode 100644 studio-desktop/src/main/java/studio/database/JsonPack.java create mode 100644 studio-desktop/src/main/java/studio/database/Library.java create mode 100644 studio-desktop/src/main/java/studio/database/LocalizedInfos.java create mode 100644 studio-desktop/src/main/java/studio/database/Person.java create mode 100644 studio-desktop/src/main/java/studio/database/Thumbnailable.java create mode 100644 studio-desktop/src/main/java/studio/localization/Translation.properties create mode 100644 studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties create mode 100644 studio-desktop/src/main/resources/META-INF/MANIFEST.MF create mode 100644 studio-desktop/src/main/resources/log4j2.xml create mode 100644 studio-desktop/src/main/resources/logolunii.jpeg create mode 100644 studio-desktop/src/main/resources/lunii.png create mode 100755 studio-desktop/src/main/resources/studio.bat create mode 100755 studio-desktop/src/main/resources/studio.sh diff --git a/pom.xml b/pom.xml index 35ae04242..c2cd2f7e4 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ driver metadata web-ui + studio-desktop diff --git a/studio-desktop/pom.xml b/studio-desktop/pom.xml new file mode 100644 index 000000000..35a44d206 --- /dev/null +++ b/studio-desktop/pom.xml @@ -0,0 +1,164 @@ + + + studio-parent + studio + 0.3.2-SNAPSHOT + + 4.0.0 + studio-desktop + + + studio + studio-core + ${project.version} + + + studio + studio-metadata + ${project.version} + + + studio + studio-driver + ${project.version} + + + com.google.code.gson + gson + + + commons-io + commons-io + + + commons-codec + commons-codec + + + com.googlecode.soundlibs + vorbisspi + 1.0.3.3 + + + com.googlecode.soundlibs + mp3spi + 1.9.5.4 + + + junit + junit + + + + + org.usb4java + usb4java + 1.3.0 + + + de.sciss + jump3r + 1.0.5 + + + org.apache.logging.log4j + log4j-api + 2.13.2 + + + org.apache.logging.log4j + log4j-core + 2.13.2 + + + org.apache.logging.log4j + log4j-jul + 2.13.2 + + + + + + src/main/java + + **/*.properties + + + + + src/main/resources + + studio.sh + studio.bat + + true + + + + src/main/resources + + studio.sh + studio.bat + lunii.png + + + .. + true + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + + copy-dependencies + prepare-package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.1.1 + + + make-assembly + package + + single + + + + + + src/main/assembly/dist.xml + + + + studio.GUI + + + + + + + + + maven-compiler-plugin + + 11 + 11 + + + + + + \ No newline at end of file diff --git a/studio-desktop/src/main/assembly/dist.xml b/studio-desktop/src/main/assembly/dist.xml new file mode 100644 index 000000000..0d0cab57b --- /dev/null +++ b/studio-desktop/src/main/assembly/dist.xml @@ -0,0 +1,42 @@ + + + + + dist + + jar + + + + + false + lib + false + compile + + + + + + ${project.build.directory} + + + ${project.build.finalName}.jar + + + + ${project.build.directory} + + + studio.sh + studio.bat + + 0755 + + + + \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java new file mode 100644 index 000000000..e7f0df0f7 --- /dev/null +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -0,0 +1,1127 @@ +package studio; + +import java.awt.BorderLayout; +import java.awt.Desktop; +import java.awt.EventQueue; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.Label; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.event.WindowEvent; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.Optional; +import java.util.ResourceBundle; +import java.util.UUID; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import javax.swing.BoxLayout; +import javax.swing.DefaultListModel; +import javax.swing.DropMode; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JProgressBar; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextField; +import javax.swing.KeyStroke; +import javax.swing.ListSelectionModel; +import javax.swing.ScrollPaneConstants; +import javax.swing.TransferHandler; +import javax.swing.UIManager; +import javax.swing.border.TitledBorder; +import javax.swing.event.ListDataEvent; +import javax.swing.event.ListDataListener; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.apache.commons.io.FileUtils; +import org.usb4java.Device; + +import studio.database.JsonPack; +import studio.database.Library; +import studio.driver.event.DeviceHotplugEventListener; +import studio.driver.event.TransferProgressListener; +import studio.driver.fs.FsStoryTellerAsyncDriver; +import studio.driver.model.TransferStatus; +import studio.driver.model.fs.FsDeviceInfos; +import studio.driver.model.fs.FsStoryPackInfos; +import studio.driver.model.raw.RawDeviceInfos; +import studio.driver.model.raw.RawStoryPackInfos; +import studio.driver.raw.RawStoryTellerAsyncDriver; +import java.awt.Toolkit; + + +public class GUI { + +// public class StoryPackInfosAndMetadata { +// protected FsStoryPackInfos pack; +// protected StoryPackMetadata metadata; +// +// protected StoryPackInfosAndMetadata(FsStoryPackInfos pack, StoryPackMetadata metadata) { +// this.pack = pack; +// this.metadata = metadata; +// } +// +// } + + private JFrame frmLuniiTransfer; + private JTextField serialNumberTextBox; + private JTextField uUIDTextBox; + private JTextField firmwareTextBox; + private JTextField totalSizeTextBox; + private JTextField usedSizeTextBox; + + private FsStoryTellerAsyncDriver fsDriver; + private RawStoryTellerAsyncDriver rawDriver; + private JList devicePacksList; + private JList libraryPacksList; + private Library library; + private DefaultListModel libraryPacksModel; + private DefaultListModel devicePacksModel; + + private boolean fsDriverUsed = false; + private boolean rawDriverUsed = false; + private JProgressBar installUninstallProgressBar; + private JProgressBar globalProgressBar; + private JLabel devicePacksSummaryLabel; + private JLabel libraryPacksSummaryLabel; + private JButton btnValidate; + private JButton btnRefresh; + private JButton btnDownloadPackages; + private JButton btnRefreshLibrary; + private ResourceBundle localization; + private Label lblTransferingPack; + + + /** + * Launch the application. + */ + public static void main(String[] args) { + EventQueue.invokeLater(new Runnable() { + public void run() { + try { + UIManager.setLookAndFeel( + UIManager.getSystemLookAndFeelClassName()); + + + + GUI window = new GUI(); + window.frmLuniiTransfer.setVisible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + } + + /** + * Create the application. + */ + public GUI() { + localization = ResourceBundle.getBundle("studio/localization/Translation", Locale.getDefault()); + + initialize(); + initializeLunii(); + + } + + private CompletableFuture> loadPacksFromDevice() { + if ( fsDriverUsed ) { + return fsDriver.getPacksList().thenComposeAsync( (List packs) -> { + return library.fetchFromServer().thenApplyAsync( (Void v) -> { + List res = packs.stream() + .map( pack -> library.getPackForUUID( pack.getUuid().toString())) + .filter( Optional::isPresent ) + .map( Optional::get ) + .toList(); + return res; + }); + }); + } else if ( rawDriverUsed ){ + return rawDriver.getPacksList().thenComposeAsync( (List packs) -> { + return library.fetchFromServer().thenApplyAsync( (Void v) -> { + List res = packs.stream() + .map( pack -> library.getPackForUUID( pack.getUuid().toString())) + .filter( Optional::isPresent ) + .map( Optional::get ) + .toList(); + return res; + }); + }); + } else { + return CompletableFuture.supplyAsync(() -> new ArrayList()); + } + } + + private void initializeLunii() { + + library = Library.getInstance(System.getProperty("user.home")); + + library.getPacks().thenAcceptAsync( (List packs) -> { + libraryPacksModel.addAll(packs); + btnRefreshLibrary.setEnabled(true); + }); + + + fsDriver = new FsStoryTellerAsyncDriver(); + rawDriver = new RawStoryTellerAsyncDriver(); + + fsDriver.registerDeviceListener(new DeviceHotplugEventListener() { + + @Override + public void onDeviceUnplugged(Device device) { + devicePacksModel.clear(); + serialNumberTextBox.setText(""); + uUIDTextBox.setText(""); + firmwareTextBox.setText(""); + totalSizeTextBox.setText(""); + usedSizeTextBox.setText(""); + + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnRefresh.setEnabled(false); + } + + @Override + public void onDevicePlugged(Device device) { + FsDeviceInfos deviceInfos; + try { + deviceInfos = fsDriver.getDeviceInfos().get(); + serialNumberTextBox.setText(deviceInfos.getSerialNumber()); + uUIDTextBox.setText(UUID.nameUUIDFromBytes(deviceInfos.getUuid()).toString()); + firmwareTextBox.setText(deviceInfos.getFirmwareMajor() + "." + deviceInfos.getFirmwareMinor()); + totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getSdCardSizeInBytes())); + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInBytes())); + + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnRefresh.setEnabled(false); + + fsDriverUsed = true; + rawDriverUsed = false; + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } + + + loadPacksFromDevice().thenAcceptAsync( (packs) -> { + devicePacksModel.clear(); + devicePacksModel.addAll(packs); + + btnDownloadPackages.setEnabled(true); + btnValidate.setEnabled(true); + btnRefresh.setEnabled(true); + }); + + } + }); + + rawDriver.registerDeviceListener(new DeviceHotplugEventListener() { + + @Override + public void onDeviceUnplugged(Device device) { + devicePacksModel.clear(); + serialNumberTextBox.setText(""); + uUIDTextBox.setText(""); + firmwareTextBox.setText(""); + totalSizeTextBox.setText(""); + usedSizeTextBox.setText(""); + + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnRefresh.setEnabled(false); + + } + + @Override + public void onDevicePlugged(Device device) { + RawDeviceInfos deviceInfos; + try { + deviceInfos = rawDriver.getDeviceInfos().get(); + serialNumberTextBox.setText(deviceInfos.getSerialNumber()); + uUIDTextBox.setText(deviceInfos.getUuid().toString()); + //uUIDTextBox.setText(deviceInfos.getUuid().toString()); + firmwareTextBox.setText(deviceInfos.getFirmwareMajor() + "." + deviceInfos.getFirmwareMinor()); + totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getSdCardSizeInSectors())); + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInSectors())); + + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnRefresh.setEnabled(false); + + fsDriverUsed = false; + rawDriverUsed = true; + + + } catch (InterruptedException | ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + loadPacksFromDevice().thenAcceptAsync( (packs) -> { + devicePacksModel.clear(); + devicePacksModel.addAll(packs); + + btnDownloadPackages.setEnabled(true); + btnValidate.setEnabled(true); + btnRefresh.setEnabled(true); + + }); + + + } + }); + +// CompletableFuture.runAsync(() -> { +// try { +// fsDriver.simulateDevicePlugged(); +// fsDriverUsed = true; +// rawDriverUsed = false; +// } catch (Exception e) { +// fsDriverUsed = false; +// rawDriverUsed = false; +// } +// }); + } + + + + /** + * Initialize the contents of the frame. + */ + private void initialize() { + frmLuniiTransfer = new JFrame(); + frmLuniiTransfer.setIconImage(Toolkit.getDefaultToolkit().getImage(GUI.class.getResource("/lunii.png")));//.getDefaultToolkit().getImage("/Users/horfee/Developpement/studio.GoodOne/studio-desktop/src/main/resources/logolunii.jpeg")); + frmLuniiTransfer.setTitle(localization.getString("Frame.Title")); + frmLuniiTransfer.setBounds(100, 100, 1024, 720); + frmLuniiTransfer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frmLuniiTransfer.getContentPane().setLayout(new BoxLayout(frmLuniiTransfer.getContentPane(), BoxLayout.X_AXIS)); + + JPanel panel = new JPanel(); + frmLuniiTransfer.getContentPane().add(panel); + panel.setLayout(new BorderLayout(0, 0)); + + JPanel panel_1 = new JPanel(); + panel.add(panel_1, BorderLayout.NORTH); + GridBagLayout gbl_panel_1 = new GridBagLayout(); + gbl_panel_1.columnWidths = new int[] {0, 0, 0, 0}; + gbl_panel_1.rowHeights = new int[] {0, 0, 0, 0, 0, 0, 0}; + gbl_panel_1.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0}; + gbl_panel_1.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; + panel_1.setLayout(gbl_panel_1); + + JLabel deviceInformationLabel = new JLabel(localization.getString("Device.Information")); + GridBagConstraints gbc_deviceInformationLabel = new GridBagConstraints(); + gbc_deviceInformationLabel.gridwidth = 4; + gbc_deviceInformationLabel.fill = GridBagConstraints.HORIZONTAL; + gbc_deviceInformationLabel.gridx = 0; + gbc_deviceInformationLabel.gridy = 0; + gbc_deviceInformationLabel.insets = new Insets(5, 5, 5, 5); + panel_1.add(deviceInformationLabel, gbc_deviceInformationLabel); + + JLabel serialNumberLabel = new JLabel(localization.getString("Device.serialnum"));//"Serial number :"); + GridBagConstraints gbc_serialNumberLabel = new GridBagConstraints(); + gbc_serialNumberLabel.anchor = GridBagConstraints.EAST; + gbc_serialNumberLabel.insets = new Insets(5, 5, 5, 5); + gbc_serialNumberLabel.gridx = 0; + gbc_serialNumberLabel.gridy = 1; + panel_1.add(serialNumberLabel, gbc_serialNumberLabel); + + serialNumberTextBox = new JTextField(); + serialNumberTextBox.setEditable(false); + GridBagConstraints gbc_serialNumberTextBox = new GridBagConstraints(); + gbc_serialNumberTextBox.weightx = 1.0; + gbc_serialNumberTextBox.gridwidth = 3; + gbc_serialNumberTextBox.insets = new Insets(5, 0, 5, 5); + gbc_serialNumberTextBox.fill = GridBagConstraints.HORIZONTAL; + gbc_serialNumberTextBox.gridx = 1; + gbc_serialNumberTextBox.gridy = 1; + panel_1.add(serialNumberTextBox, gbc_serialNumberTextBox); + serialNumberTextBox.setColumns(10); + + JLabel uUIDLabel = new JLabel(localization.getString("Device.UUID"));//:"); + GridBagConstraints gbc_uUIDLabel = new GridBagConstraints(); + gbc_uUIDLabel.anchor = GridBagConstraints.EAST; + gbc_uUIDLabel.insets = new Insets(5, 5, 5, 5); + gbc_uUIDLabel.gridx = 0; + gbc_uUIDLabel.gridy = 2; + panel_1.add(uUIDLabel, gbc_uUIDLabel); + + uUIDTextBox = new JTextField(); + uUIDTextBox.setEditable(false); + GridBagConstraints gbc_uUIDTextBox = new GridBagConstraints(); + gbc_uUIDTextBox.weightx = 1.0; + gbc_uUIDTextBox.gridwidth = 3; + gbc_uUIDTextBox.insets = new Insets(5, 0, 5, 5); + gbc_uUIDTextBox.fill = GridBagConstraints.HORIZONTAL; + gbc_uUIDTextBox.gridx = 1; + gbc_uUIDTextBox.gridy = 2; + panel_1.add(uUIDTextBox, gbc_uUIDTextBox); + uUIDTextBox.setColumns(10); + + JLabel FirmwareLabel = new JLabel(localization.getString("Device.firmware"));//"Firmware :"); + GridBagConstraints gbc_FirmwareLabel = new GridBagConstraints(); + gbc_FirmwareLabel.anchor = GridBagConstraints.EAST; + gbc_FirmwareLabel.insets = new Insets(5, 0, 5, 5); + gbc_FirmwareLabel.gridx = 0; + gbc_FirmwareLabel.gridy = 3; + panel_1.add(FirmwareLabel, gbc_FirmwareLabel); + + firmwareTextBox = new JTextField(); + firmwareTextBox.setEditable(false); + GridBagConstraints gbc_firmwareTextBox = new GridBagConstraints(); + gbc_firmwareTextBox.weightx = 1.0; + gbc_firmwareTextBox.gridwidth = 3; + gbc_firmwareTextBox.insets = new Insets(5, 0, 5, 5); + gbc_firmwareTextBox.fill = GridBagConstraints.HORIZONTAL; + gbc_firmwareTextBox.gridx = 1; + gbc_firmwareTextBox.gridy = 3; + panel_1.add(firmwareTextBox, gbc_firmwareTextBox); + firmwareTextBox.setColumns(10); + + JLabel sizeLabel = new JLabel(localization.getString("Device.size")); + GridBagConstraints gbc_sizeLabel = new GridBagConstraints(); + gbc_sizeLabel.anchor = GridBagConstraints.EAST; + gbc_sizeLabel.insets = new Insets(5, 5, 5, 5); + gbc_sizeLabel.gridx = 0; + gbc_sizeLabel.gridy = 4; + panel_1.add(sizeLabel, gbc_sizeLabel); + + totalSizeTextBox = new JTextField(); + totalSizeTextBox.setEditable(false); + GridBagConstraints gbc_totalSizeTextBox = new GridBagConstraints(); + gbc_totalSizeTextBox.weightx = 1.0; + gbc_totalSizeTextBox.insets = new Insets(5, 0, 5, 5); + gbc_totalSizeTextBox.fill = GridBagConstraints.HORIZONTAL; + gbc_totalSizeTextBox.gridx = 1; + gbc_totalSizeTextBox.gridy = 4; + panel_1.add(totalSizeTextBox, gbc_totalSizeTextBox); + totalSizeTextBox.setColumns(10); + + JLabel sizeUsedLabel = new JLabel(localization.getString("Device.used")); + GridBagConstraints gbc_sizeUsedLabel = new GridBagConstraints(); + gbc_sizeUsedLabel.insets = new Insets(5, 5, 5, 5); + gbc_sizeUsedLabel.anchor = GridBagConstraints.EAST; + gbc_sizeUsedLabel.gridx = 2; + gbc_sizeUsedLabel.gridy = 4; + panel_1.add(sizeUsedLabel, gbc_sizeUsedLabel); + + usedSizeTextBox = new JTextField(); + usedSizeTextBox.setEditable(false); + GridBagConstraints gbc_usedSizeTextBox = new GridBagConstraints(); + gbc_usedSizeTextBox.weightx = 1.0; + gbc_usedSizeTextBox.insets = new Insets(5, 0, 5, 5); + gbc_usedSizeTextBox.fill = GridBagConstraints.HORIZONTAL; + gbc_usedSizeTextBox.gridx = 3; + gbc_usedSizeTextBox.gridy = 4; + panel_1.add(usedSizeTextBox, gbc_usedSizeTextBox); + usedSizeTextBox.setColumns(10); + + JPanel panel_3 = new JPanel(); + panel.add(panel_3, BorderLayout.SOUTH); + GridBagLayout gbl_panel_3 = new GridBagLayout(); + gbl_panel_3.columnWidths = new int[] {0, 0, 0, 0}; + gbl_panel_3.rowHeights = new int[] {0}; + gbl_panel_3.columnWeights = new double[]{0.0, 1.0, 0.0, 1.0}; + gbl_panel_3.rowWeights = new double[]{0.0}; + panel_3.setLayout(gbl_panel_3); + + lblTransferingPack = new Label();//"Transfering pack {}"); + GridBagConstraints gbc_lblTransferingPack = new GridBagConstraints(); + gbc_lblTransferingPack.anchor = GridBagConstraints.WEST; + gbc_lblTransferingPack.insets = new Insets(5, 5, 5, 5); + gbc_lblTransferingPack.gridx = 0; + gbc_lblTransferingPack.gridy = 0; + panel_3.add(lblTransferingPack, gbc_lblTransferingPack); + + installUninstallProgressBar = new JProgressBar(); + GridBagConstraints gbc_installUninstallProgressBar = new GridBagConstraints(); + gbc_installUninstallProgressBar.fill = GridBagConstraints.HORIZONTAL; + gbc_installUninstallProgressBar.insets = new Insets(5, 0, 5, 5); + gbc_installUninstallProgressBar.gridx = 1; + gbc_installUninstallProgressBar.gridy = 0; + panel_3.add(installUninstallProgressBar, gbc_installUninstallProgressBar); + + Label lblProgress = new Label(localization.getString("Transfer.globalProgress"));//"Progress"); + GridBagConstraints gbc_lblProgress = new GridBagConstraints(); + gbc_lblProgress.anchor = GridBagConstraints.WEST; + gbc_lblProgress.insets = new Insets(5, 0, 5, 5); + gbc_lblProgress.gridx = 2; + gbc_lblProgress.gridy = 0; + panel_3.add(lblProgress, gbc_lblProgress); + + globalProgressBar = new JProgressBar(); + GridBagConstraints gbc_globalProgressBar = new GridBagConstraints(); + gbc_globalProgressBar.fill = GridBagConstraints.HORIZONTAL; + gbc_globalProgressBar.insets = new Insets(5, 0, 5, 5); + gbc_globalProgressBar.gridx = 3; + gbc_globalProgressBar.gridy = 0; + panel_3.add(globalProgressBar, gbc_globalProgressBar); + + devicePacksModel = new DefaultListModel(); + + + DragSource ds = new DragSource(); + DragGestureListener dgl = new DragGestureListener() { + + @Override + public void dragGestureRecognized(DragGestureEvent dge) { + String source = dge.getComponent().getName(); + if ( source.equals("devices") || source.equals("library") ) { + String selectedIndices = ((JList)dge.getComponent()).getSelectedValuesList().stream().map( JsonPack::getUuid ).collect(Collectors.joining(",")); + StringSelection transferable = new StringSelection(source + ": " + selectedIndices); + ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, null); + } + }}; + + libraryPacksModel = new DefaultListModel(); + devicePacksModel.addListDataListener(new ListDataListener() { + + @Override + public void intervalAdded(ListDataEvent e) { + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); + + } + + @Override + public void intervalRemoved(ListDataEvent e) { + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); + + } + + @Override + public void contentsChanged(ListDataEvent e) { + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); + + } + + }); + libraryPacksModel.addListDataListener(new ListDataListener() { + + @Override + public void intervalAdded(ListDataEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); + + } + + @Override + public void intervalRemoved(ListDataEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); + + } + + @Override + public void contentsChanged(ListDataEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); + + } + + }); + + JPanel panel_7 = new JPanel(); + panel_7.setBorder(null); + panel.add(panel_7, BorderLayout.CENTER); + GridBagLayout gbl_panel_7 = new GridBagLayout(); + gbl_panel_7.columnWidths = new int[]{0, 0}; + gbl_panel_7.rowHeights = new int[]{0, 0}; + gbl_panel_7.columnWeights = new double[]{1.0, Double.MIN_VALUE}; + gbl_panel_7.rowWeights = new double[]{1.0, Double.MIN_VALUE}; + panel_7.setLayout(gbl_panel_7); + + JSplitPane splitPane = new JSplitPane(); + splitPane.setResizeWeight(0.5); + GridBagConstraints gbc_splitPane = new GridBagConstraints(); + gbc_splitPane.fill = GridBagConstraints.BOTH; + gbc_splitPane.gridx = 0; + gbc_splitPane.gridy = 0; + gbc_splitPane.insets = new Insets(0, 5, 0, 5); + panel_7.add(splitPane, gbc_splitPane); + + JPanel panel_2 = new JPanel(); + splitPane.setLeftComponent(panel_2); + panel_2.setLayout(new BorderLayout(0, 0)); + + JScrollPane devicePacksScrollPane = new JScrollPane(); + panel_2.add(devicePacksScrollPane); + devicePacksList = new JList(devicePacksModel); + devicePacksList.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + + if ( e.getExtendedKeyCode() == KeyEvent.VK_DELETE ) { + int[] selection = devicePacksList.getSelectedIndices(); + for(int i = selection.length - 1; i >= 0; i--) { + devicePacksModel.remove(selection[i]); + } + } else if ( e.getExtendedKeyCode() == KeyEvent.VK_ESCAPE ) { + devicePacksList.getSelectionModel().clearSelection(); + } + } + }); + devicePacksList.setBorder(new TitledBorder(null, localization.getString("Device.list"), TitledBorder.LEADING, TitledBorder.TOP, null, null)); + devicePacksList.setCellRenderer( new JsonPackCell()); + devicePacksList.setName("devices"); + devicePacksScrollPane.setViewportView(devicePacksList); + devicePacksList.setDragEnabled(true); + devicePacksList.setDropMode(DropMode.INSERT); + devicePacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); + + } + + }); + ds.createDefaultDragGestureRecognizer(devicePacksList, DnDConstants.ACTION_MOVE, dgl); + devicePacksList.setTransferHandler(new TransferHandler() { + + private static final long serialVersionUID = -6050701764610620507L; + + public boolean canImport(TransferHandler.TransferSupport support) { + if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { + return false; + } + if ( !support.getComponent().getName().equals("devices")) { + return false; + } + + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + return dl.getIndex() != -1; + } + + public boolean importData(TransferHandler.TransferSupport support) { + if (!canImport(support)) { + return false; + } + + Transferable transferable = support.getTransferable(); + String transferMe; + try { + transferMe = (String)transferable.getTransferData(DataFlavor.stringFlavor); + } catch (UnsupportedFlavorException | IOException e) { + e.printStackTrace(); + return false; + } + + String source = transferMe.substring(0, transferMe.indexOf(": ")); + List uuids = List.of(transferMe.substring(transferMe.indexOf(": ") + 2).split(",")); + + JList list = source.equals("library") ? libraryPacksList : source.equals("devices") ? devicePacksList : null; + if ( list == null ) return false; + + final DefaultListModel model = ((DefaultListModel)list.getModel()); + + List indices = new ArrayList(); + for(String uuid :uuids ) { + indices.add(IntStream.range(0, model.getSize()) + .filter( i -> uuid.equals(model.get(i).getUuid())) + .findFirst() + .getAsInt()); + } + + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + final Integer dropTargetIndex = dl.getIndex(); + + if ( source.equals("devices") ) { + int nbBeforeDropIndex = (int)indices.stream().filter( (v) -> v < dropTargetIndex.intValue() ).count(); + List objects = new ArrayList(); + for(int index = indices.size() - 1; index >= 0; index-- ) { + objects.add(model.remove(indices.get(index))); + } + + int insertIndex = dropTargetIndex - nbBeforeDropIndex; + + for(int i = objects.size() - 1; i >= 0; i-- ) { + model.add(insertIndex++, objects.get(i)); + + } + } else { + List existingPacks = List.of( ((DefaultListModel)((JList)support.getComponent()).getModel()).toArray()); + List existingUUIDs = existingPacks.stream() + .map( p -> ((JsonPack)p).getUuid() ) + .toList(); + + List toAdd = indices.stream() + .map( i -> model.get(i)) + .filter( pack -> existingUUIDs.stream().allMatch(s -> !s.equalsIgnoreCase(pack.getUuid())) ) + .toList(); + devicePacksModel.addAll(dropTargetIndex, toAdd); + } + + + return true; + } + + }); + + JPanel panel_4 = new JPanel(); + panel_2.add(panel_4, BorderLayout.SOUTH); + GridBagLayout gbl_panel_4 = new GridBagLayout(); + gbl_panel_4.columnWeights = new double[]{0.0, 0.0, 0.0, 1.0}; + gbl_panel_4.rowWeights = new double[]{0.0}; + panel_4.setLayout(gbl_panel_4); + + btnDownloadPackages = new JButton(localization.getString("Device.download"));//"Download"); + btnDownloadPackages.setEnabled(false); + GridBagConstraints gbc_btnDownloadPackages = new GridBagConstraints(); + gbc_btnDownloadPackages.anchor = GridBagConstraints.NORTHWEST; + gbc_btnDownloadPackages.insets = new Insets(0, 0, 0, 5); + gbc_btnDownloadPackages.gridx = 0; + gbc_btnDownloadPackages.gridy = 0; + panel_4.add(btnDownloadPackages, gbc_btnDownloadPackages); + btnDownloadPackages.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + int[] selected = devicePacksList.getSelectedIndices(); + if ( selected.length == 0 ) { + selected = IntStream.range(0, devicePacksModel.getSize()).toArray(); + } + Arrays.stream(selected).boxed().map( (i) -> devicePacksModel.get(i)).forEach( (pack) -> { + if ( fsDriverUsed ) { + fsDriver.downloadPack(pack.getUuid(), library.getLibraryPath(), new TransferProgressListener() { + + @Override + public void onProgress(TransferStatus status) { + installUninstallProgressBar.setMinimum(0); + installUninstallProgressBar.setMaximum(status.getTotal()); + installUninstallProgressBar.setValue(status.getTransferred()); + + } + + @Override + public void onComplete(TransferStatus status) { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + + } + }); + } else if ( rawDriverUsed ) { + try { + rawDriver.downloadPack(pack.getUuid(), Files.newOutputStream(Paths.get(library.getLibraryPath(), pack.getUuid() + ".pack")), new TransferProgressListener() { + + @Override + public void onProgress(TransferStatus status) { + installUninstallProgressBar.setMinimum(0); + installUninstallProgressBar.setMaximum(status.getTotal()); + installUninstallProgressBar.setValue(status.getTransferred()); + + } + + @Override + public void onComplete(TransferStatus status) { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + + } + }); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + }); +// for(int i : selected) { +// if ( fsDriverUsed ) { +// fsDriver.downloadPack(null, null, null) +// } +// } + } + }); + + btnValidate = new JButton(localization.getString("Device.validate"));//"Validate"); + btnValidate.setEnabled(false); + GridBagConstraints gbc_btnValidate = new GridBagConstraints(); + gbc_btnValidate.anchor = GridBagConstraints.NORTHWEST; + gbc_btnValidate.insets = new Insets(0, 0, 0, 5); + gbc_btnValidate.gridx = 1; + gbc_btnValidate.gridy = 0; + panel_4.add(btnValidate, gbc_btnValidate); + btnValidate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + loadPacksFromDevice().thenAcceptAsync( (packs) -> { + try { + + List uuids = packs.stream().map( pack -> pack.getUuid()).toList(); + List uuidsInList = Arrays.asList(devicePacksModel.toArray()).stream().map( pack -> ((JsonPack) pack).getUuid()).toList(); + + // Packs to uninstall + List toUninstall = new ArrayList(uuids); + toUninstall.removeAll(uuidsInList); + + // Packs to add + List toInstall = new ArrayList(uuidsInList); + toInstall.removeAll(uuids); + + int nbSteps = toUninstall.size() + toInstall.size() + 1; + + globalProgressBar.setMinimum(0); + globalProgressBar.setMaximum(nbSteps); + globalProgressBar.setValue(0); + if ( fsDriverUsed ) { + toUninstall.forEach( (pack) -> { + try { + String packTitle = library.getPackForUUID(pack).get().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.deletingpack").replace("{}", packTitle)); + fsDriver.deletePack(pack).get(); + } catch (InterruptedException | ExecutionException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + } + }); + } else if ( rawDriverUsed ) { + toUninstall.forEach( (pack) -> { + try { + String packTitle = library.getPackForUUID(pack).get().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.deletingpack").replace("{}", packTitle)); + rawDriver.deletePack(pack).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + } + }); + } + + + TransferProgressListener progressListener = new TransferProgressListener() { + + @Override + public void onProgress(TransferStatus status) { + installUninstallProgressBar.setMinimum(0); + installUninstallProgressBar.setMaximum(status.getTotal()); + installUninstallProgressBar.setValue(status.getTransferred()); + + } + + @Override + public void onComplete(TransferStatus status) { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + } + }; + + if ( fsDriverUsed ) { + toInstall.forEach( (pack) -> { + try { + String packTitle = library.getPackForUUID(pack).get().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); + fsDriver.uploadPack(pack, library.getFolderForUUID(pack), progressListener).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + } + }); + } else if ( rawDriverUsed ) { + toInstall.forEach( (pack) -> { + try { + // TODO : getAckInputStream + String packTitle = library.getPackForUUID(pack).get().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); + rawDriver.uploadPack(null, 0, progressListener).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + } + }); + } + + // Reorder packs + if ( fsDriverUsed ) { + try { + lblTransferingPack.setText(localization.getString("Transfering.reordering")); + fsDriver.reorderPacks(uuidsInList).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + } + } else { + try { + rawDriver.reorderPacks(uuidsInList).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + + } + } + + } catch(Exception e2) { + e2.printStackTrace(); + } + + }); + } + }); + + btnRefresh = new JButton(localization.getString("Device.refresh"));//"Refresh from device"); + btnRefresh.setEnabled(false); + GridBagConstraints gbc_btnRefersh = new GridBagConstraints(); + gbc_btnRefersh.anchor = GridBagConstraints.NORTHWEST; + gbc_btnRefersh.insets = new Insets(0, 0, 0, 5); + gbc_btnRefersh.gridx = 2; + gbc_btnRefersh.gridy = 0; + panel_4.add(btnRefresh, gbc_btnRefersh); + btnRefresh.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnRefresh.setEnabled(false); + + devicePacksModel.clear(); + loadPacksFromDevice().thenAcceptAsync( (packs) -> { + devicePacksModel.clear(); + devicePacksModel.addAll(packs); + + btnDownloadPackages.setEnabled(true); + btnValidate.setEnabled(true); + btnRefresh.setEnabled(true); + }); + + } + }); + + devicePacksSummaryLabel = new JLabel("-/-"); + GridBagConstraints gbc_devicePacksSummaryLabel = new GridBagConstraints(); + gbc_devicePacksSummaryLabel.anchor = GridBagConstraints.EAST; + gbc_devicePacksSummaryLabel.gridx = 3; + gbc_devicePacksSummaryLabel.gridy = 0; + panel_4.add(devicePacksSummaryLabel, gbc_devicePacksSummaryLabel); + + JPanel panel_5 = new JPanel(); + splitPane.setRightComponent(panel_5); + panel_5.setLayout(new BorderLayout(0, 0)); + + JPanel panel_6 = new JPanel(); + panel_5.add(panel_6, BorderLayout.SOUTH); + GridBagLayout gbl_panel_6 = new GridBagLayout(); + gbl_panel_6.columnWeights = new double[]{0.0, 1.0}; + gbl_panel_6.rowWeights = new double[]{0.0}; + panel_6.setLayout(gbl_panel_6); + + btnRefreshLibrary = new JButton(localization.getString("Library.refresh"));//"Refresh library"); + btnRefreshLibrary.setEnabled(false); + GridBagConstraints gbc_btnRefreshLibrary = new GridBagConstraints(); + gbc_btnRefreshLibrary.anchor = GridBagConstraints.NORTHWEST; + gbc_btnRefreshLibrary.insets = new Insets(0, 0, 0, 5); + gbc_btnRefreshLibrary.gridx = 0; + gbc_btnRefreshLibrary.gridy = 0; + panel_6.add(btnRefreshLibrary, gbc_btnRefreshLibrary); + btnRefreshLibrary.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + btnRefreshLibrary.setEnabled(false); + libraryPacksModel.clear(); + //libraryPacksList.setListData(new JsonPack[0]); + library.refreshDatabase().thenRunAsync( () -> { + library.getPacks().thenAcceptAsync( (List packs) -> { + libraryPacksModel.addAll(packs); + btnRefreshLibrary.setEnabled(true); + + }); + }); + + } + }); + + libraryPacksSummaryLabel = new JLabel("-/-"); + GridBagConstraints gbc_libraryPacksSummaryLabel = new GridBagConstraints(); + gbc_libraryPacksSummaryLabel.anchor = GridBagConstraints.EAST; + gbc_libraryPacksSummaryLabel.gridx = 1; + gbc_libraryPacksSummaryLabel.gridy = 0; + panel_6.add(libraryPacksSummaryLabel, gbc_libraryPacksSummaryLabel); + + + + JScrollPane libraryPacksScrollPane = new JScrollPane(); + panel_5.add(libraryPacksScrollPane); + libraryPacksScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); + libraryPacksList = new JList(libraryPacksModel); + libraryPacksList.setBorder(new TitledBorder(null, localization.getString("Library.list"), TitledBorder.LEADING, TitledBorder.TOP, null, null)); + libraryPacksScrollPane.setViewportView(libraryPacksList); + libraryPacksList.setName("library"); + libraryPacksList.setCellRenderer( new JsonPackCell()); + libraryPacksList.setDragEnabled(true); + libraryPacksList.addMouseListener( new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + JList list = (JList)evt.getSource(); + if (evt.getClickCount() == 2) { + int index = list.locationToIndex(evt.getPoint()); + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Locale currentLocale = Locale.getDefault(); + JsonPack story = libraryPacksModel.get(index); + String slug = story.getSlug(); +// if ( story.getPreviews() != null && story.getPreviews().size() > 0 ) { + try { +// String storyName = story.getPreviews().get(0).split("/")[3];// story.getTitle().replaceAll(" ", "-").toLowerCase(); + String url = "https://lunii.com/" + currentLocale.getCountry().toLowerCase() + "-" + currentLocale.getLanguage() + "/luniistore-catalogue/" + slug; + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException e1) { + } +// } else { +// story.getLocalizedInfos().entrySet().stream().filter( (infos) -> infos.getValue().getPreviews().size() > 0).findFirst().ifPresent( ( entrySet ) -> { +// String storyName = entrySet.getValue().getPreviews().get(0).split("/")[3];// story.getTitle().replaceAll(" ", "-").toLowerCase(); +// String url = "https://lunii.com/" + currentLocale.getCountry().toLowerCase() + "-" + currentLocale.getLanguage() + "/luniistore-catalogue/" + storyName; +// try { +// Desktop.getDesktop().browse(new URI(url)); +// } catch (IOException | URISyntaxException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } +// }); +// } + + } + } + } + }); + libraryPacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); + + } + + }); + libraryPacksList.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + + if ( e.getExtendedKeyCode() == KeyEvent.VK_ESCAPE ) { + libraryPacksList.getSelectionModel().clearSelection(); + } + } + }); + + + ds.createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); + + libraryPacksList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + //TransferHandler transferHandler = libraryPacksList.getTransferHandler(); + + JMenuBar menuBar = new JMenuBar(); + frmLuniiTransfer.setJMenuBar(menuBar); + + JMenu mnNewMenu = new JMenu(localization.getString("File.title"));//"File"); + mnNewMenu.setMnemonic('F'); + menuBar.add(mnNewMenu); + + JMenuItem mntmNewMenuItem = new JMenuItem(localization.getString("File.quit"));//"Quit"); + mntmNewMenuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + frmLuniiTransfer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frmLuniiTransfer.dispatchEvent(new WindowEvent(frmLuniiTransfer, WindowEvent.WINDOW_CLOSING)); + + } + }); + + JMenuItem changeLibraryPathMenuItem = new JMenuItem(localization.getString("Library.changePath"));//"Change library path..."); + changeLibraryPathMenuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + chooser.setCurrentDirectory(new java.io.File(library.getLibraryPath())); + chooser.setDialogTitle(localization.getString("Library.ChooseLibraryFolder"));//"Choose library folder"); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if ( chooser.showOpenDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION ) { + library = Library.getInstance(chooser.getSelectedFile().getAbsolutePath()); + btnRefreshLibrary.doClick(); + } + } + }); + mnNewMenu.add(changeLibraryPathMenuItem); + mntmNewMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.META_DOWN_MASK)); + mnNewMenu.add(mntmNewMenuItem); + + + } + + + +// + +class MyListDropHandler extends TransferHandler { + private static final long serialVersionUID = -6453689410470088604L; + + JList list; + + public MyListDropHandler(JList list) { + this.list = list; + } + + public boolean canImport(TransferHandler.TransferSupport support) { + if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { + return false; + } + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + return dl.getIndex() != -1; + } + + public boolean importData(TransferHandler.TransferSupport support) { + if (!canImport(support)) { + return false; + } + + Transferable transferable = support.getTransferable(); + Object indexString; + try { + indexString = (Object)transferable.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + return false; + } + + List indices = Arrays.stream(indexString.toString().split(",")).mapToInt(Integer::parseInt).boxed().toList();//.sorted(Collections.reverseOrder()).toList(); + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + final Integer dropTargetIndex = dl.getIndex(); + + int nbBeforeDropIndex = (int)indices.stream().filter( (v) -> v < dropTargetIndex.intValue() ).count(); + + List objects = new ArrayList(); + for(int index = indices.size() - 1; index >= 0; index-- ) { + objects.add(((DefaultListModel)list.getModel()).remove(indices.get(index))); + } + + int insertIndex = dropTargetIndex - nbBeforeDropIndex; + + for(int i = objects.size() - 1; i >= 0; i-- ) { + ((DefaultListModel)list.getModel()).add(insertIndex++, objects.get(i)); + + } + + return true; + } +} +} diff --git a/studio-desktop/src/main/java/studio/JsonPackCell.java b/studio-desktop/src/main/java/studio/JsonPackCell.java new file mode 100644 index 000000000..c02badeac --- /dev/null +++ b/studio-desktop/src/main/java/studio/JsonPackCell.java @@ -0,0 +1,187 @@ +package studio; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +import javax.swing.DefaultListModel; +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import javax.swing.UIManager; +import javax.swing.border.Border; +import javax.swing.plaf.UIResource; + +import studio.database.JsonPack; +import studio.database.LocalizedInfos; + + +class JsonPackCell implements ListCellRenderer, UIResource { + + private static final long serialVersionUID = -9095012373460466070L; + + + private static final Border noBorder = UIManager.getBorder("List.cellNoFocusBorder"); + private static final Border selectedAndFocusedBorder = UIManager.getBorder("List.focusSelectedCellHighlightBorder"); + private static final Border focusBorder = UIManager.getBorder("List.focusCellHighlightBorder"); + + JsonPackCell() { + super(); + initialize(); + + } + + + private JPanel initialize() { + JPanel res = new JPanel(); + GridBagLayout gridBagLayout = new GridBagLayout(); + gridBagLayout.columnWeights = new double[]{0.0, 1.0}; + res.setLayout(gridBagLayout); + + JLabel icon = new JLabel(); + icon.setName("icon"); + icon.setPreferredSize(new Dimension(64, 64)); + GridBagConstraints gbc_icon = new GridBagConstraints(); + gbc_icon.gridheight = 3; + gbc_icon.insets = new Insets(5, 5, 5, 5); + gbc_icon.gridx = 0; + gbc_icon.gridy = 0; + res.add(icon, gbc_icon); + + JLabel title = new JLabel(); + title.setText("title"); + title.setName("title"); + GridBagConstraints gbc_title = new GridBagConstraints(); + gbc_title.anchor = GridBagConstraints.WEST; + gbc_title.insets = new Insets(5, 5, 5, 5); + gbc_title.gridx = 1; + gbc_title.gridy = 0; + res.add(title, gbc_title); + + JLabel subTitle = new JLabel(); + subTitle.setText("subTitle"); + subTitle.setName("subtitle"); + GridBagConstraints gbc_subTitle = new GridBagConstraints(); + gbc_subTitle.anchor = GridBagConstraints.WEST; + gbc_subTitle.insets = new Insets(0, 5, 5, 5); + gbc_subTitle.gridx = 1; + gbc_subTitle.gridy = 1; + res.add(subTitle, gbc_subTitle); + + + JLabel ageLabel = new JLabel(); + ageLabel.setText("age"); + ageLabel.setName("age"); + GridBagConstraints gbc_ageLabel = new GridBagConstraints(); + gbc_ageLabel.anchor = GridBagConstraints.WEST; + gbc_ageLabel.insets = new Insets(0 , 5, 5, 5); + gbc_ageLabel.gridx = 1; + gbc_ageLabel.gridy = 2; + res.add(ageLabel, gbc_ageLabel); + + res.setPreferredSize(new Dimension(412, 64)); + + return res; + } + + @Override + public Component getListCellRendererComponent(JList list, JsonPack value, int index, + boolean isSelected, boolean cellHasFocus) { + + JPanel res = this.initialize(); + res.setComponentOrientation(list.getComponentOrientation()); + + Color bg = null; + Color fg = null; + + JList.DropLocation dropLocation = list.getDropLocation(); + if (dropLocation != null + && !dropLocation.isInsert() + && dropLocation.getIndex() == index) { + + bg = (Color)UIManager.get("List.dropCellBackground"); + fg = (Color)UIManager.get("List.dropCellForeground"); + + isSelected = true; + } + + if (isSelected) { + res.setBackground(bg == null ? list.getSelectionBackground() : bg); + res.setForeground(fg == null ? list.getSelectionForeground() : fg); + } + else { + if ( index % 2 == 0 ) { + res.setBackground(list.getBackground()); + } else { + res.setBackground(new Color(240, 240, 240)); + } + + res.setForeground(list.getForeground()); + } + + Border border = null; + if (cellHasFocus) { + if (isSelected) { + border = selectedAndFocusedBorder; + } + if (border == null) { + border = focusBorder; + } + } else { + border = noBorder; + } + res.setBorder(border); + + + + LocalizedInfos defaultLocalizedInfos = value.getLocalizedInfos().values().iterator().next(); + List components = List.of(res.getComponents()); + + components.stream().filter( (c) -> "icon".equals(c.getName())).findFirst().ifPresent( ( c) -> { + if ( defaultLocalizedInfos.hasFetchImage() ) { + ((JLabel)c).setIcon(new ImageIcon(defaultLocalizedInfos.getThumbnail())); + } else { + + CompletableFuture.runAsync(() -> { + defaultLocalizedInfos.getThumbnail(); + DefaultListModel model = (DefaultListModel) list.getModel(); + model.setElementAt(value, index); + }); + } + + }); + //icon.setData(defaultLocalizedInfos); + + + + components.stream().filter( (c) -> "title".equals(c.getName())).findFirst().ifPresent( ( c) -> { + String strTitle = value.getTitle(); + if ( strTitle == null ) strTitle = defaultLocalizedInfos.getTitle(); + ((JLabel)c).setText(strTitle); + }); + //title.setText(strTitle); + + components.stream().filter( (c) -> "subtitle".equals(c.getName())).findFirst().ifPresent( ( c) -> { + String strSubTitle = value.getSubtitle(); + if ( strSubTitle == null ) strSubTitle = defaultLocalizedInfos.getSubtitle(); + ((JLabel)c).setText(strSubTitle); + }); + + components.stream().filter( (c) -> "age".equals(c.getName())).findFirst().ifPresent( ( c) -> { + String strAge = value.getAgeMax() == -1 ? "From " + value.getAgeMin() + " years": "From " + value.getAgeMin() + " to " + value.getAgeMax() + " years"; + ((JLabel)c).setText(strAge); + }); + //subTitle.setText(strSubTitle); + + + return res; + } + + } \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/database/JsonPack.java b/studio-desktop/src/main/java/studio/database/JsonPack.java new file mode 100644 index 000000000..76f3beaa9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/database/JsonPack.java @@ -0,0 +1,125 @@ +package studio.database; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import com.google.gson.annotations.SerializedName; + +public class JsonPack { + + @SerializedName("uuid") + private String uuid; + + @SerializedName("age_max") + private int ageMax; + + @SerializedName("age_min") + private int ageMin; + + @SerializedName("creation_date") + private Date creationDate; + + + @SerializedName("slug") + private String slug; + + @SerializedName("modification_date") + private Date modificationDate; + + @SerializedName("duration") + private int duration; + + @SerializedName("is_factory") + private boolean isFactory; + + @SerializedName("title") + private String title; + + @SerializedName("subtitle") + private String subtitle; + + @SerializedName("night_mode_playable") + private boolean nightMode; + + @SerializedName("keywords") + private String keywords; + + @SerializedName("authors") + private Map authors; + + @SerializedName("previews") + private List previews; + + @SerializedName("tellers") + private Map tellers; + + @SerializedName("localized_infos") + private Map localizedInfos; + + + public String getSlug() { + return slug; + } + + public String getUuid() { + return uuid; + } + + public int getAgeMax() { + return ageMax; + } + + public int getAgeMin() { + return ageMin; + } + + public Date getCreationDate() { + return creationDate; + } + + public Date getModificationDate() { + return modificationDate; + } + + public int getDuration() { + return duration; + } + + public boolean isFactory() { + return isFactory; + } + + public String getTitle() { + return title; + } + + public String getSubtitle() { + return subtitle; + } + + public boolean isNightMode() { + return nightMode; + } + + public String getKeywords() { + return keywords; + } + + public Collection getAuthors() { + return authors.values(); + } + + public List getPreviews() { + return previews; + } + + public Collection getTellers() { + return tellers.values(); + } + + public Map getLocalizedInfos() { + return localizedInfos; + } +} \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/database/Library.java b/studio-desktop/src/main/java/studio/database/Library.java new file mode 100644 index 000000000..c9832c734 --- /dev/null +++ b/studio-desktop/src/main/java/studio/database/Library.java @@ -0,0 +1,241 @@ +package studio.database; + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.Type; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.annotations.SerializedName; + +import studio.core.v1.model.metadata.StoryPackMetadata; +import studio.core.v1.reader.archive.ArchiveStoryPackReader; +import studio.core.v1.reader.binary.BinaryStoryPackReader; +import studio.core.v1.reader.fs.FsStoryPackReader; + +public class Library { + + public static final String TOKEN_URL = "https://server-auth-prod.lunii.com/guest/create"; + public static final String DATABASE_URL = "https://server-data-prod.lunii.com/v2/packs"; + public static final String RESOURCE_URL = "https://storage.googleapis.com/lunii-data-prod"; + + private JsonResponse officalPacksDatabase; + + private static volatile Library instance; + + private String libraryPath; + + public static Library getInstance(String path) { + if (instance != null && instance.libraryPath.equals(path)) { + return instance; + } + synchronized(Library.class) { + if (instance == null || !instance.libraryPath.equals(path)) { + instance = new Library(path); + } + return instance; + } + } + + private Library(String path) { + officalPacksDatabase = null; + this.libraryPath = path; + } + + public String getLibraryPath() { + return libraryPath; + } + + public String getFolderForUUID(String uuid) { + try { + return Files.list(Paths.get(libraryPath)).filter( (path) -> { + Optional res = this.readPackFile(path); + if ( res.isPresent() && res.get().getUuid().equals(uuid)) return true; + return false; + }).findFirst().get().toString(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return null; + } + + private Optional readPackFile(Path path) { + // Handle all file formats + if (path.toString().endsWith(".zip")) { + try (FileInputStream fis = new FileInputStream(path.toFile())) { + System.out.println("Reading archive pack metadata in folder " + path.toString()); + ArchiveStoryPackReader packReader = new ArchiveStoryPackReader(); + StoryPackMetadata meta = packReader.readMetadata(fis); + if (meta != null) { + System.out.println("Pack found for UUID " + meta.getUuid()); + //return Optional.of(new LibraryPack(path, Files.getLastModifiedTime(path).toMillis() , meta)); + Optional res = officalPacksDatabase.getPacks().stream().filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); + if ( !res.isPresent() ) { + System.out.println("Package not found for UUID " + meta.getUuid()); + } + return res; + } + System.out.println("No pack found..."); + return Optional.empty(); + } catch (IOException e) { + System.out.println("Failed to read archive-format pack " + path.toString() + " from local library"); + //e.printStackTrace(); + return Optional.empty(); + } + } else if (path.toString().endsWith(".pack")) { + try (FileInputStream fis = new FileInputStream(path.toFile())) { + System.out.println("Reading raw pack metadata in folder " + path.toString()); + BinaryStoryPackReader packReader = new BinaryStoryPackReader(); + StoryPackMetadata meta = packReader.readMetadata(fis); + if ( meta != null && meta.getUuid() != null ) { + System.out.println("Pack found for UUID " + meta.getUuid()); + Optional res = officalPacksDatabase.getPacks() + .stream() + .filter( (JsonPack p) -> + p.getUuid().equalsIgnoreCase(meta.getUuid())) + .findFirst(); + if ( !res.isPresent() ) { + System.out.println("Package not found for UUID " + meta.getUuid()); + } + return res; + } + System.out.println("No pack found..."); + return Optional.empty(); + } catch (IOException e) { + System.out.println("Failed to read raw format pack " + path.toString() + " from local library"); + //e.printStackTrace(); + return Optional.empty(); + } + } else if (Files.isDirectory(path)) { + try { + System.out.println("Reading FS pack metadata in folder " + path.toString()); + FsStoryPackReader packReader = new FsStoryPackReader(); + StoryPackMetadata meta = packReader.readMetadata(path); + if (meta != null) { + System.out.println("Pack found for UUID " + meta.getUuid()); + Optional res = officalPacksDatabase.getPacks().stream().filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); + if ( !res.isPresent() ) { + System.out.println("Package not found for UUID " + meta.getUuid()); + } + return res; + } + System.out.println("No pack found..."); + return Optional.empty(); + } catch (Exception e) { + System.out.println("Failed to read FS format pack " + path.toString() + " from local library"); + //e.printStackTrace(); + return Optional.empty(); + } + } + + // Ignore other files + return Optional.empty(); + } + + + + public CompletableFuture refreshDatabase() { + officalPacksDatabase = null; + return getPacks(); + } + + + public CompletableFuture fetchFromServer() { + + return CompletableFuture.runAsync( () -> { + if ( officalPacksDatabase != null ) return; + try { + URL getToken = new URL(TOKEN_URL); + InputStream stream = getToken.openStream(); + + JsonObject response = new Gson().fromJson(new InputStreamReader(stream), JsonObject.class); + + String token = response.getAsJsonObject("response").getAsJsonObject("token").get("server").getAsString(); + + URL getDatabase = new URL(DATABASE_URL); + URLConnection connection = getDatabase.openConnection(); + connection.addRequestProperty("X-AUTH-TOKEN", token); + + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(Date.class, new JsonDeserializer() { + + @Override + public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return new Date(json.getAsLong()); + } + + }); + + Gson gson = builder.create(); + officalPacksDatabase = gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonResponse.class); + + System.out.println(officalPacksDatabase.getPacks().stream().map( (p) -> p.getUuid()).toList()); + } catch(NullPointerException e) { + e.printStackTrace(); + } catch (MalformedURLException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + + } + + public Optional getPackForUUID(String uuid) { + if ( officalPacksDatabase == null ) return null; + return officalPacksDatabase.getPacks().stream().filter( (pack) -> pack.getUuid().equalsIgnoreCase(uuid)).findAny(); + } + + public CompletableFuture> getPacks() { + return fetchFromServer().thenComposeAsync( (Void v) -> { + return CompletableFuture.supplyAsync(() -> { + try { + return Files.list(Paths.get(libraryPath)) + .map( this::readPackFile ) + .filter( Optional::isPresent ) + .map( Optional::get ) + .toList(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return new ArrayList(); + }); + }); + } + + protected class JsonResponse { + + @SerializedName("response") + private Map packs; + + public Collection getPacks() { + return packs.values(); + } + + + } +} diff --git a/studio-desktop/src/main/java/studio/database/LocalizedInfos.java b/studio-desktop/src/main/java/studio/database/LocalizedInfos.java new file mode 100644 index 000000000..0203deb45 --- /dev/null +++ b/studio-desktop/src/main/java/studio/database/LocalizedInfos.java @@ -0,0 +1,76 @@ +package studio.database; + +import java.net.URL; +import java.util.List; + +import org.apache.commons.io.IOUtils; + +import com.google.gson.annotations.SerializedName; + +public class LocalizedInfos extends Thumbnailable { + + protected class JsonImage { + @SerializedName("image_url") + private String url; + + public String getUrl() { + return url; + } + + } + + @SerializedName("description") + private String description; + + @SerializedName("image") + private JsonImage image; + + @SerializedName("subtitle") + private String subtitle; + + @SerializedName("title") + private String title; + + @SerializedName("previews") + private List previews; + + public String getDescription() { + return description; + } + + public String getImageUrl() { + return image.getUrl(); + } + + public String getSubtitle() { + return subtitle; + } + + public String getTitle() { + return title; + } + + public List getPreviews() { + return previews; + } + + private byte[] imageData; + + + public boolean hasFetchImage() { + return imageData != null; + } + + public byte[] getImage() { + if ( this.imageData != null ) return imageData; + try { + + URL url = new URL(Library.RESOURCE_URL + this.getImageUrl().replaceAll("\\s", "%20")); + return imageData = IOUtils.toByteArray(url); + } catch (Exception e) { + } + return new byte[0]; + + } + +} \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/database/Person.java b/studio-desktop/src/main/java/studio/database/Person.java new file mode 100644 index 000000000..8ddbf35e1 --- /dev/null +++ b/studio-desktop/src/main/java/studio/database/Person.java @@ -0,0 +1,43 @@ +package studio.database; + +import java.net.URL; + +import org.apache.commons.io.IOUtils; + +import com.google.gson.annotations.SerializedName; + +public class Person extends Thumbnailable { + @SerializedName("gender") + private String gender; + + @SerializedName("name") + private String name; + + @SerializedName("image") + private String image; + + public String getGender() { + return gender; + } + + public String getName() { + return name; + } + + public String getImageUrl() { + return image; + } + + private byte[] imageData; + + public byte[] getImage() { + if ( this.imageData != null ) return imageData; + try { + URL url = new URL(Library.RESOURCE_URL + this.image); + return imageData = IOUtils.toByteArray(url); + } catch (Exception e) { + } + return new byte[0]; + } + +} \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/database/Thumbnailable.java b/studio-desktop/src/main/java/studio/database/Thumbnailable.java new file mode 100644 index 000000000..4f2e27675 --- /dev/null +++ b/studio-desktop/src/main/java/studio/database/Thumbnailable.java @@ -0,0 +1,45 @@ +package studio.database; + +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import javax.imageio.ImageIO; + +public abstract class Thumbnailable { + + public abstract byte[] getImage(); + + private byte[] thumbnailImage; + + public byte[] getThumbnail() { + if ( thumbnailImage != null ) return thumbnailImage; + + + try { + BufferedImage source = ImageIO.read(new ByteArrayInputStream(getImage())); + BufferedImage bimage = new BufferedImage(64, 64, BufferedImage.TYPE_INT_ARGB); + + // Draw the image on to the buffered image + Graphics2D bGr = bimage.createGraphics(); + bGr.setRenderingHint(RenderingHints.KEY_INTERPOLATION, + RenderingHints.VALUE_INTERPOLATION_BILINEAR); + bGr.drawImage(source, 0, 0, 64, 64, 0, 0, source.getWidth(null), source.getHeight(null), null); + bGr.dispose(); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ImageIO.write(bimage, "png", baos); + + thumbnailImage = baos.toByteArray(); + } catch (IOException e) { + thumbnailImage = new byte[0]; + } + + return thumbnailImage; + + } + +} diff --git a/studio-desktop/src/main/java/studio/localization/Translation.properties b/studio-desktop/src/main/java/studio/localization/Translation.properties new file mode 100644 index 000000000..225bb705d --- /dev/null +++ b/studio-desktop/src/main/java/studio/localization/Translation.properties @@ -0,0 +1,21 @@ +Frame.Title=Lunii Transfer +Device.Information=Device information: +Device.serialnum=Serial number: +Device.UUID=UUID: +Device.firmware=Firmware: +Device.size=Size : +Device.used=Used : +Device.download=Download +Device.list=Device +Device.validate=Commit +Device.refresh=Refresh +Transfering.transferringpack=Transferring pack {} +Transfering.deletingpack=Deleting pack {} +Transfering.reordering=Ordering packs +Transfer.globalProgress=Progress +Library.list=List +Library.refresh=Refresh library +File.title=File +File.quit=Quit +Library.changePath=Change library path... +Library.ChooseLibraryFolder=Choose file \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties new file mode 100644 index 000000000..d297ba522 --- /dev/null +++ b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties @@ -0,0 +1,21 @@ +Frame.Title=Lunii Transfert +Device.Information=Information sur la lunii: +Device.serialnum=Numéro de série: +Device.UUID=UUID: +Device.firmware=Firmware: +Device.size=Taille : +Device.used=Utilisé : +Device.download=Télécharger +Device.list=Boite lunii +Device.validate=Valider +Device.refresh=Rafraichir +Transfering.transferringpack=Transfert du pack {} +Transfering.deletingpack=Suppression du pack {} +Transfering.reordering=Tri des packs +Transfer.globalProgress=Progression +Library.list=Liste +Library.refresh=Rafraichir la librairie +File.title=Fichier +File.quit=Quitter +Library.changePath=Changer le répertoire de la librairie... +Library.ChooseLibraryFolder=Choisir le répertoire \ No newline at end of file diff --git a/studio-desktop/src/main/resources/META-INF/MANIFEST.MF b/studio-desktop/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 000000000..78692c366 --- /dev/null +++ b/studio-desktop/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +Created-By: Apache Maven 3.9.0 +Built-By: horfee +Build-Jdk: 19.0.2 +Main-Class: studio.GUI + diff --git a/studio-desktop/src/main/resources/log4j2.xml b/studio-desktop/src/main/resources/log4j2.xml new file mode 100644 index 000000000..f41508df6 --- /dev/null +++ b/studio-desktop/src/main/resources/log4j2.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/studio-desktop/src/main/resources/logolunii.jpeg b/studio-desktop/src/main/resources/logolunii.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..5341b4d6faba2f07bb23f8cb3f50368568fe7c45 GIT binary patch literal 70565 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%0D6e+*vDK-| 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 G+5g$^ja`cX literal 0 HcmV?d00001 diff --git a/studio-desktop/src/main/resources/lunii.png b/studio-desktop/src/main/resources/lunii.png new file mode 100644 index 0000000000000000000000000000000000000000..4aeec981f7201791fac0437b68d320d5bba45bd9 GIT binary patch literal 255552 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 z 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�n{@^%4f<<1g+@ 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 QipG14x^8ufrW**DD2=h2 z47m3RZ)NH3+Dd=#r1;;n1;5}68Fr)qxHGk@V;DJaO(>nOQ2u*UPAE8tnp~o8+W_n4 zS99QvT{DDS6*_hp0FC)cr#=kQOVO}?!K2*@kWR-=4ttPVloqF{mThF_>a1|;`>IBg zaf^(Hc^|0iF7n)guADyVy|WnKjK)$- z#zT`|Pb)Zr4#ULE_x@p!+^J%;5j~K)=e^G|M6653SWepYtJ>eSw>TfVb|8t&gj`m#hc6(gsA%tScSYR%8a!h zcxW-)02m6B&1uJC)r3sn(&-E$wOZ!$Mk@uJsggWQkS4rXSyX%Ll;_jbBMWI)E+JOy zB~15!pI~a*#&Jib#Gf6#p>uLZ(^)Uh1l$U$151WFc+aM|CVe`z!;NXECF8V{pPE|0 zOn#Wq=5snr^x%}Ea}#W&ON!z)R3(rndW~Zhe1XpB{i8xn-MZoae4XS zuy_o6b%A^TPVYZ>mvTLFKL}u3V*@G~r#Fd*kuOLih@+gc%!@Rsx5i1r1N@Uq%-}On z8$Jfs!5|oQM_WWigkn`m%fO)X1RzjJ&j;5<8ZY0tfBHQ8Gw@%r|7wjWWv;_(u1X-X z%1vklh6om}*<7&9r5p0sBPYb=haMmXy3)|IGV4>{zwY6gcaDz_;8rD*s;PlY6!v$E zdA}VGMRn&}1J$=aCod@QABB?>{FzMO#|?8+Z>Y*y^TQ-eIP;yGLSFf_xis}-KOKiXWart| z?YM%sI7Cma7rKpp)LLFiu|&zd8oDRGPO-(CAMV{$L&#( zy`Z1Xax5R4lD_V6ftZTj_qHuG@B4uTXiX5=w}28Gs;kcEw8Y3h`9_(YoBYcU@7SE} zhy6<$tn&7u%<)r25OrfZoxqb=t>BCPiz6LIZ@ATVaHfcEPO^gk7pOcWDfWR&UtihmbLl%R zM`NUEGC{hHCn+*w&v#Kka(>sdjjy1GNMT7W|6E1GP@ zpV#I;{A9iE^QKi1e;f+V%dgSBz|o@X6^W}10>7F;Y*$veI}=n;am|e;J58;LYuLACHaaku%8dK~YW< zzT0n{Nf=wL`cH&ky>!Tt$hl#UPJcTFv4|mW>TPzgc^HV^j0M;Jk?=n24n=UBF=^vfI+mb}*y&jU;^%47rKk*m}DUUc!160lsmwn$23_$#r@sEV!e~ERnR4YB&U` z2+WEg-$KgzlNjPoD`%7}%Y=5TwLMc)TNV*}t+PJ~yIRud4Dp|tQb z-wm(R6IaYZm8@ztvv2B@8iy#du>VtJp(zD@%0`cg_-ziTRx?h}?J)5wcvx#V=r_SG zcC-vzF}oeas{Z|^>S&^c507a~QqSyhx)k0HedYCUAOsfl*XX*Fh%l0ro6lzAC%jd9 z`d@TE)7c++N9K+rYxnMVsYXfF?o1Z3GfS-_<1XXVTuiBoxlg^RpAy&x-)C!x(sy72 zhKO3lvffFIfK(2ULMz_{wM-o^RonK?yJFoF1f90%1I~GwKPo@9nmIc%I7%PJjH3oI z75~tQvh9v;i9mH}kY}n-B)Ff6+kr!P7(f; z^2RT}`FM?S*kQUB9j(+41!{&UG5_;uc_E-nyc*CngJsgdXKf*an+p3^U2C=z8}ZSP z2Ghv4rh3dmq&$L6;p66w$JJ5#g4cJ#yTS@}iD`vLPTyU0WXA%=GwQBf*&AIk}V>qleHmd2*1OYd)IIPUYmsneYn zI-N++ZKG}3L2~P8ZaktTowTEfxr$lok9zsY0yZNJ#Eg=)TBWy_pnPk`Br?OlPCQkx z3M(!D@ENDq^*j1GMa<8m%Smvq!Hg<38}2RG;Y_sI{p7F3eS6(Y(P(HkKZL?gR*A&y zV)M)6o~MJ<@ZD2KP9ndAP*b(P&|v3+STeCeJ{6%<@*|uYOhp=b;F-q4aD*oX^rXiN zq;od>;wtE2fagYu3TW!3wL@T9mgmB_h9#~xG*yAZ#3?t;YN|JEzg+b@TGI0hhul-a zRLInfRPb`+%p02^xsO~dWyWb$+d~>UrE)Yl5#g&Pcr2Z^-V50md^rjSa}_=dSB);x z!b(t4qZj$rT0%KATAudvMflK0dHLUmhV$+OmS(IAr;u~rE@VbkQ{&vAj8q~3(2f4y z5$p>S|>YH21HBafvJHQB`Fdy5*n{u)4!?0+2eXOr!_X> zNd{h(tZJ((J=wIHCh;E0mk>hjiMDZ+Pb$z5$O=u|^cme*H2YNj35y$3VNH{{`)RfC zro!7J$N*ByK^FExXbj+>g2E4q`LWkkD=cEDhqJPh2~mEaJW+f?SD=;z77rJZ65_%{ zMjL+24jK&As5Szl2&9Tz!}b*l9oHaD z@N^plkdJ0K_(}g zueA@ACA>jQ@72X2;=`{@tosTo+yV*v*sWi&h*5Bqb1_I68Cs*)?G)6acXw1dGZ$Ro z0|aJ{DY@yaO#l1-rdww|UgHmSmb;KUghh-BF!8gW9HQpzxF~iWThqK^va9?Bdv#6- zsYBh-Ai$%LRaIN51LTo#!?&#;Nmtz*_=wtHo)|9eieyBOGRh1jzXJ`;cv=zVA9xI$ z3Ag6gfWmr-aE!S$(XMv6NmJu8T+iJ;u8g<%&X49P^KdA686LNQZ6#HVw<}zk14mz-=csKL18Etf3Oz?GhO4bHyji@Ei64`g^ zh|6-r+tlcymRqmE1=6yoU9uMZHD)WLBSHCTv$ngG?m$ZVoc#%Q760Ow%SooV6$Zp% zlxsNCcNGpucJl(Sn_lTe)Qo{V7w((LB`r?~HYYvyv9$RBqmCj10Ye zHM%H#o$hzaHRV9MJPpas^%!+iq-=CaB0J^0oTp2>HG1RKKC$!MDWhW09hSaZ5*pNP zCkA|ES0F!#OrH!aAX(+BPwVoS$4r8Qx8LWvr`a!IcqIN^y>S%$75>NS7+M;CScf3l z3@)zFHzg*_y1FE^1d>lwq=@h-Xu=g+HqCL9cIV>>aV?rkZ7lCF=Qqghgg@x7I(M%O*z*%n@q_#0wN>AOB$w4HKrlJGLDwGv-!^-TR#e(DUTe*)8kzlF_;Zub7taZ z?bj2Ptfm-q*k@nC5H^9s5n8j-Zo>_E)M-kTB+zM@gwunjeb*DAl2GzRdeSb60?JK5 z6rkD9`0>83Y9eKuX&V|@pi8>lAE2N4f#2ZfYWq)Prnnoz=%|hhdP2*?c{)@4J&|9) z0aj~;)A^%Y@|awuj=Tj#ulxM3(Tgl7S^M_&Uyea(w~xQCmHv;p?0o60U?R*tbd9=^ zWb0U(C^)-?vicDs2@sH(vX2!GHChu^8UsRex^MZDcI0;Q7&z1EZ&`f0zR7pL$?*>&(TeR2On&_kO-zAE=HoQ)|f$q6`R9wYyZ25T)0>Le?Jf+0t1r->K%uXVyDZ-pgSky;k1Y~}QJv#mUdtpvIFM9h`FuHr`#{93fbd2uHy@Z9g#l~W2)LT4oUu1hwnG^!fQmZtSl%S; z?|Gp=VwGaGA4*_zp46m!5vq5*0&@_+%8fB!g*QmKGjT%J&A=?qt~1sEg(|SyE@zTh zrEAfvMGV?4$c-E}>B z!<10IZoy{AlvWx|E8KTQ)XZj<&`DNh+O7}J?P4NSY3&_TnA~TVgR#gLn5$;wl@e`A zAREkWVH-s^oN%LZl&FUqmrNpP7{ZSO6cMr20+%FI_yv}nH!tf$-^6xjUKeJs=OF$a zfP#xYDeGh6%l9L)7p|#y|+iz4?9smF~B&Q@ph7y8=u=B~t zW9MJ4=pYZHk-xLg{D6MNuS_L1Nf~H$z;fY-{s-B9mKJO<_Rl-H-0TzoZQ%*Si>2Fy zW-(i8#)0in4vp8n`4=G8iu-b+uoe0~X2Kujivartp~^?!DG_r(j!Y10RE|ftPZNu{ zxDUvY(I?NpQ2j*H1}QN%9&kEdo}>K|LaKcm^eZN#T}~W%%le2_N0X?t&JZFm_3ySE z+imwF5O>JOEv36>Dzpei6MRL+!&dJ7wgPlNz7{`PZ`-E@K-dA4NfeRc?xAm`!g`Wk=n01GuHOV89JJ zd{EtI!WnWh*~0A7mAXS6)5fE7MAEr<)Z*yLr+`^tC~1q*^CWqb=x=MD_G_n~R!~BA zM4RBjG9|6ALyeZ-to8AdvEvOo^K6yv6Ow*B(uYd5?`o>96s>=18Y*XbmU8)<)ny@2 z38`TQ%m6G>LAr`8ZWXQHbHukaj6Sl`*hb zqXFB&L>5BO3Lg^YR6x2El5Et%vf7-8Fsk1HQCi28hb5|RciKld9hIIszk6XvCtpfR z$dn^IS?jk*jjC>$eH#EX0^|MO7q;?|FuS@Hvjx&<{wwo}1L6cA2~Nco~h&&<^7VL`+ z#v#MAsZnSjA4#l8j({biQT?5ND|S(tvN%!;L8l>BzRq1k9=r&itKpjl-cl^2Gw!M?(t9m^+-1OA`5_% ztm8h^t)v!Ebfg{JFA6!V@-KctJn_^O044k|fuDb~lMV>!F#^BLAeJh>qp!y#?E+ z+*ww;V+rR2d6XLF;-}x9nK7hJuEtOU|KLze4QVN%Bz);vj49KD{3@S#SH{_NVL6uZ z&85HNP~#{5@_qD`xyVdV)g0Yey3Pi z&&MD2?dU^C{A9*}H0@3e^hK(R@4S4$S8)fCPOtbR0`8QfmhnQ4tf{j!2~ zLUbi5!>|ITu6lJf*|=gGp9Bw-qoRTnmE#5}yc=tUF=k1rWDvutKFxwpqmf(t%>$1*3F zJjeHwV{Sd|Sx0CC04Z4fjCOwagMGhr**MNT z7|@3q(t>1eI08e`kT|1nd;DMG4^U~eVaz~Zy%850?JI3y_ktH*`gP~TX1h`qH4&!q z?5>NyIx!3Ui*y_L5$mmn+w!Xq_%N~DN0%4ziv+k7m*%vp#atQ#5GshmDbFq)jBBLS z$ILd1bXbo8{7{tX2Yn#Ku7o{Ch4I-+@&<5Ve7)!%K*BaH(y z28k7(CVxAtm{kk#8wNEhY&0|?NvF57r|5brXF{d;YiwCs>O5vP1GLJ+62@>KQ`^+C;>p~r8oDvW@2Ji9jO>;@sBGzpg{ToA4|dp z0re-3Hz?Zn6H^m?BSwpno-*5)+qA-q)-(9Z5F-eQ8Nx`TN3SWz&v2=8u{GV*(jotH zzHqWj1QCoQPW~8LGxODSGT6-SraF6c&h=vWn=eqX{)jiG16 z)O~hk`X{(R-8R?8*h)*Y|CS!SsScBpAzmk|g#E1~#FJ9OM)6s2s`+&5p}RYfpEo7o zOagriKO2I7+>U2AxUv4zxAx%iH`+ZnR=<}I@`Q2p;` zPpb|8y*mgo!&(zCx}t0XM`nVHq~t4q-s+~Ga+lh%C=0aI-+4Q@wV3&sb>!QGPJAcW ziQ(_@FIYN`la?q;K>_uihqWH-lA~6gERs=DsX9@a09(c0@S}WfbwE}|An;O$Rurc6u4=k;3FUZ1PfV9THX9~VGMNVIt!Sy}~AD0@^D zuhm@QJ53z3MF|=zMtoK5KWUZukh;^kN%sUpQL{@oxniumoV~Lb*BA`;uYT7uUt|?( z-2~{N|M0{qN8c85W5HmrQ^KT9<~$I8^y||_|HAwqA>ImGofu>EZ;g!%bz6Vv$fl2< z70mXW8XXuH=7?|V{Jd>S5)1v0337_|Ye7J*Z?}q-Rcm!AW?eF(b%KS94~edhBblW;>z~8m#jkaBmbw zz-fxctR$tk844d^w^HkO`&t5Kun%%Pm8 zz%M_=?Oga;=@A!t8%j##b5GGX?dirWPSfpQwP7nS5gbh7!&aYXfJcxg4v`l1d2MTdqI6*iJD5qOKzCfFP92i?e##m9 z47Udiee3JV$(|6V&q318;k03phLy;k8Q8B^L}I@DppUJ+W4wnkT>F8$Q0@2S+7B9w z4Q*Hk{bRBiw9c&iKNECkE}MtK`2;;aasor^1P%tNad1oIe6}yq5JF<0j*#L;&ZTS_qLoHx)W}ZZ}wNmZrB* zwL(2mEup|8*>qdc*eHk3?l6Sf9+OKRY2I+M(uih^+!7~<)f_QjdGY?aA_&Snd`9`) z`oZXOA6fb$*)Q8{dz%A1O;hKLQIZOmHcLxt5~I2Gk@08iQtTa^L7beZf5w7=4>GsWkK(5A5xxOKB}nrwu3=Ffhu{lxEB9BUvxD zhLkHwakhMS{#-@giss+9W0R3UpQ@bQ;Y{%e3`lnt@y(jd@&!o7r0wY4sr9jG1OsP< zw;!NCDe%_ldP#;r-K{Z%3geo?=t0?Jp|8toIG5wARLgKK`~Z2GS_lKfP3?E?>6?k- zG-)cU2h{|9r&SXXO{%VG2R?IIzPsvtgi)buulm@iN34-tx)K4pMCR)}PJ7+9T&*%$^%|lX$qm7791vT=X-PgoKe|oIun;5QF`R@nthSIkEi9dpd7lmEdy%m_Qw*)iM@#R;ua8joTCV#5BETb@x6W$EI zKKDV2<{t*hnqR9m@moODO%OKN8q?k#?(^%0brg_$l830`%h-tAxY0V}pNeq4NnA*U zdnpIVsl$2NHGagW#efIr)cEaU7w=ek!h*>th#PAp0hCxMbItti0}f$ne>q%}=rqq+VBSgXuo@yb#1 z6%_8J=K@;8!4(*uAENNQqu!JPZCU&VChF>T_-n03Mr$Fn%1dRS`{{y$p%!9hl^I|lzaj#r+T*WId{``U7K+oh))Lr}rEl(}LMskDXs!fGNv zY3a_E1I4%1Sq#_D_sWCebSOQdHFQ{Gm|-@vPYrHY`}J$SElN=+KK~J-{$IiK3iMQX ze4)E8W^=qIX*6HKuwUZP7&a$tC!-|B%6@axlyXh$){?9lH|MRDFOEOQ+__izZF6pH z4y+48;EH+k*Kr+FXwj{5^ORjuPtjub@J1xm*~}rope%~n#z@I`KxxSNeF zAfP{ApzC#AZQ7kB7}G`RgIBr`p965PGf+UNYp)Ys)gXj}XHSxfTYV?;7&=E<(iKR> zVZ|(RQ^j^9_wRO*!y_j9UB5^RkTm3FCE19)+deXEA?v5o=r2QvkWLM%Xud7wF8opx zf~XwUt10w4Akg(G??g3IEdvh}Rc9J*${wrxu(2eSQ>rOME~E_@T|`mS;I|N`)8ON2 zuyD6y}@j$|oDvIo4(oo1@f`4_`UHnES_5I>vL;ZZU80}hE7@S_O z!~{A5++|vXkSOm2^a!Xr8krL-FJx-u1_!Ck*+Q)<6KEpC(<0+Z-7$?j49`kZ4A4_5 zPF|EL`am))S_@J?lPG-{hcw1CE(>JK5?u2UPCD*0?6Et)&vl4iIc;i&e$ke zQ|>%dR9@!RB*Tm75<5yh8>V!2f8yryUi@cE=Xdo|?jDu!&Z6-^96i$|S5bRA!A8SU zT^(=WOxv*-t^bh%PX(36l?slPq(|aT=kH$eo%fx=xLZw7E&d{!j>sJ>t}zbwmAl{g zQLm@}i6^O7Co-vOjb&IxxR^@Za6s`xZYRC|QZ< ze_`{4ptMv=1MFYH+jZ!&9n>~;`-oAYG^47D09oPjxO+n%e)_pfnCN+vEZ6#<55{VT ziG9}Prtp|=-}{`)jw4=4hQ~>iqenBMnHLIrkYgzEWj)MGOQ0Jj3`{VlG`xmE-~Tn% zVl^5C?xsEu;=c1D+JWu}!`l!(u6pH`MB($f{cdxbl7K?CWx(rs zC33ie&t-!*dWI2ej5hS9NN$Wfb!N!?jNTxsWBe`TKDar;IA?%Ux-=`~^o)M|=28s_ zkIFXbvr*Z4!U*AS~aR-CHO<`3sF-jq$}+A zi)@9F=suSkN67YkuU3vP5r%H53kbDj3cuYBZ6DND#|CIs&zYVP@IlB>k&uFI{m}ec zJu9U5;w}wR%DBZA!a7l~s;K0bNQy41He7sIySMJP2(4^)%lnwM)HA<8dN9pH3O(n) zM*Ex**v8*{_;ZHCm+dVtI!qee>~JYdGCU6eY?0yNr4c=%xx+hTSM|M#@eq(%tA|oz zvZ?ySc9-=@0mhK?DW%CA?|F#v+z8m22w#*_;%2&F6BJbbO5Kc6ER&Wfs#CFbY0YoZ zsA>LQMc3o)WFCjDaQwIPT)IJ7^S{2d`DW`5hLg_6yR*ig5&*$lalx3ULZeUj_WIO; z_EW1LoPz9(0T7E?UR1TSv2GU+wVCIArTQ+N0e{jV^(dU7w?XoUmx@6NR=a#Yv=_`J zbMak6@!y0J1m-JLl9R8`3koJ4tx0fJ>c;848KVP_zLBPRa*^BJ6C zBO2mk3L{lyol?mUB~?Pt)!PgZAIVVo_h5gXGLd{I#_Ltv<~5}(J}LbC`D~^3bH>NN z+xVg7X=VjH#94~1cq^A^p{O(BWpPImt^UB_u2LctbZ%N+$0(A{siTk5rsqllHmq+QH$&qmU*}$!KEv{jCzn{Y02htE z(JXguhr+qXRKAPTwGk2g{UTt7lNsIB{~?)=eESe@>YZ+M902eWe0tPOGuuqk^+1K@`}ewo zz_UmFGF2Q@BhAz5lm(-%;R`q`&KkoC(xgbE48}jd^M1L{CjN;50hEZ8j6bv9t}nuf z=%OBP%T^;Dp?lw-L^^6{(u|i`O9_T5bprc|xUuS!D()Ek4)us4+tn5J?*z}IBjoN3 zTjW3_A@4Hq51?M;V2178kj!3w@MgTvxz)d=2h>v+ylzHqPSpyK^L5Yy5!3w{4L3~uw>ZH_<<+g}MHT>7?HDcd-65%? z*OeWNDhv>t?d89E*?!adXj$>mnl#)5t6i0Fk7Lp#LbP$+C~-ZvUbRhC>6_R0LjjZ6 zLn^h(&5XzX87)u0GYbX<5v}yf9N)m3$Ln9@0U#0Qx#`lb%)Iy0)de|SE(34~3DznW zKSr8aXFFY-Skvana-+ke@d&yuU{UR2m`nkvw9f4g0Xyhn08iji-W|}j8^(vE6_ku9 z)e1L|HvexAiyRtx8Q)M}9+Zh4khm>B9~Q@aMdom~3Ck66?{Al#nwLj6_&+p#Wn7f+ z^EE6BF47>KOLqv;-Q6A1ozl`vBi$k0APv$DA|S1FOLqt&{oH(i&;O0@@Uz!FSDZO# z=FG{(b&`P;gT5puZP5i&Qo@jrcmf)0=Bfvxq&G10LF`Zaip|;-7?BKwu z$V$K3buzSopj!u6Nj^A)KqA*@WM>uUzeJGSetXcjwSm>|Z1q&=^sEQ{`!&d4 z(`=6Wd^44|yf2e%<4z9SPg~+zOx(}*BTyh8l&P^Twm3;sen=ww^0)Uo3ZlSLY&D>g z=#Cny;u#j2g49E>2%vwZuzYH0vml*TLv9SV|JS-AI1iArOt3+n#&3}+fC)p2(i`1= zCw+9%m*3BRhMlv79#9PSi4Hq}Sg+wbgIWh=@-tlM(Joqwtp}h#@?SR`R8)^R8Q$Je zn7K`N1_+B?uacBpQ4O2a~jg3I7ozUg^5lNM_Y31}^l zH_xUeGIDm)~FMG7cNcm{Jt1RudMIO?&68@z%FLer&9Q=M!vCILM3K zv%=|N4D=i|=`>M{iEbpEW@ki|BHz#capvqJ`iBLsTeug*u|0>ePVUrxYk{VQKkCLl zQ@E@0z4NKdY{K`6X2!GCm6lx!6pufOFT^eQm(9RGP>&&%HuIpcyMUD1VI^8AmLxSF za$}29@Q~)Lx=)!Qf^~6Y{mI2Wcwku=>7Dq=hC|@;v5cpT*{A1WVmmBh=H%O0~_iG;K^x0JYYf zd^`~Z{b;Dj`vo39ACf0u*!6L8=^$-Kh`3iOInZETe}?K?ogd%vW|oRc!Q zt@Bs@_7gnRb7+;#DG#{`8y@}0zNGP+zatSaGh1+{-Y;M^;VdfYQdlw=S1a@^L3D_F z2ND06hn`!hOrVa6aZux9WcW zTq{jYE?`m6JF+;a6Ms74=g@5`sP<*{(1Qq&^C-Ky85QL|(wNmwealV(9wyM38JB<( zu0)wq$#1=*KesC1m#Lg`kekThxv87i__oM+;9*9VXN^afw=pOZsm`LfBs_)fx~(%} zeG)WsQ|uo$0Gyr#tHbV*7J4trG-lzV-h9utM?I*sb%NV60oIQX%JA3;{IOE?_SUF% zD7H5tDCSC=XJq=`cRTGY5OEF9V`pfNnD8b8Ae|*>FuiNIYhnqyplV75%)nH_`vJ>{ zC6NGfoXF3;$eF)pzxZ^lucosP40xy7_ zst9{a`@XwW-^Zvb=QqI0MPmW1TyzfmsnY{^PP=o`k$HEL*-YboDD5u7y%*8!wrChH z6=5(u8?QzLJ2^miwK6($_t&Kn$vqD`tfw|64e^+tU;>y~KO<+rc<3_Y5H`ILrR z6|>SZf)M-uls}E^dHXAiAlK>3fZYgD3J4~qZhUh_xFi;P^8$OX>V?-HsrdXq7C?fA zl(X*@xgF$@@l5@R5AkVz|0OLUnBo)j+@K(+WOn}P9mbHPhj9EPFw4Hj50h5@9mWf|t%?-1-$@5Q(VfK`-V^#N25yP4n z@}@_ksf>Bpc=rTI(bG#*+b^D0F6^L;RZ$knamT{Eb?|l)*}`@jStf%*{1~rp56~nt zJ*dAn0V-r@4l*1^bw!Q#AjK5O-$og#WESt8nt@?E3`dum-eFP&&N5eZ^A?&s>lvM}@A?9$cRhL5JU zP(Ek`n{tTqvH+6gHkT6X@yMe|fc~?5r_d&#Ngd%}cI~Ye=y5kxQy*s1dBCFcW_)G} zatIvC4u`LelRHlJ7VfBauwDqWF)%GE1&&DGtx>Eux2P^XBJIbo(8AGfz1Z?(z|`rd zoQX&CeQ6u#UAF^KFv%;TLx^Luha?A|-DWS1GN{0yD8_aUtwUH)8evs3Tp-pnRbj7s z(wDgmb8lp`*&zHSNV}RJWVUF}BMJlWm(`MtsQkIq5r=&%VsLAG(FtGjfjBiT^ymf$* zkJoj(Q{)tk{XSLPLb6tDv~NI>GRj59-d%}x<^DimXMdH>9UGgB31^=GBt47GI4!?G zdYj4g)UU$v$mcV;ZYTCBOM#a3)ZUrygJY%yIvKRxc${ zllT-iAFiIWrRv$vO{m{uXrH_-CFSJn^bF+f)VUZZ4gOyvK{gG&r%o#AEa~pnJ${`P zMnrBmtsiNpJi(HaZrpSo6RnGlDOlv|0uOW)7jW|q^a3{2SmFDp-6!u{w|e~YPmm@N zfQD?7JJcv(AP^$rV8^hR*WVwjEnPtuoG@(~7j>Q8&p#U5R8T9K$;A-YB50e!O=VGC z$fYjdUK6l+>wSE5jY{n;E%cq(onGolqi?~vb9INDC3 z8kffm3vrSOl=dql$z~AGMQuIi6xJx}j+ZMmgM{*zYg+Y>S%0B*z0|rjLWPJ{HQFg; zuuty&cxAOX@g_%T#GqF^1sU5FSUe_ah%P_H zzuB&=-y{N#vc!}&VP7m>{Lxa@u0+@-N}QFce57qF6eRheu07p^5snw_I+SnbIBKafMKpj&iu$?~N9=oiY(bbi1Kijw!tR(BWElMVd6I5$X zL$gVcn9~d+u(m{uAl0aX>2?kBt8yAO!@ExUmbyBF3p7qy$W21<9QR>8$TMH&B1{oS zL0aCRfrRp!i1YHPYwA#>b3a=R9n1aoXN|a(uazgTbGR3&nHL_7Y~nBrbpJY2EcRhk zB5>|px>cN(eH@Hu#hGWgl=Enm9;AsK6V*S^#i=?HeJ-XWN32H8711`RAgYf%x+Ul^ zg1_F~rp`yTw&rrAn9qkCV<45)=)A&2i^&9ARVV8x<-JVuqYrbW9uZB##X!~uC;8~6 zg+&rWXxySwgJP@V!q3!NDyC<;Pw%y@)B~~XBU(SuPC>y{r+<3hYdJ02ZJL`-5#b4s zMuDIc;5PVcuh#oLy6Ifw&K`+`bM}{2P{0>Ei#sB>+NX|$<9(@e%7#Xqk_b$mbgn(6(~khT(}yKt_*a;|%&qyGD!PARB5sMIsiL&Kx#DR@lF^*Ua;t%!m#% zgF*76N8sN}M8f-fqtOFABqnmQPg{DQKim(}E~9UVVPDU3PgT9XvLmv!6aRJW+`-@7nKoTRx$ zB?p<$PKfjTUo8Nbi!R;BO`Z1Qf%m@85$N}!qOh7^rsG864znvbt58bAY*$Y33wj7K zo@WW`>f0~MZwen8a`OK&_I#Y8Y(BVU2|AI6i&{)&KWusv72~N+Qqd6%flow>Qu~?L`4mG&xgba}Ic56>zq{J} z8@}_{y|qdJbx+7kKLIzj=S16XA{iy@I``pM*5>cFj>gBro^Zuth_z=-f}lbYs!)Te zDi>I@7woJ^N;yLnU{Jc75H86W7v`4#Z_CQbOhUDHs{%YZl}>x$VO=~vE3*Pe4k&NE zi8vWvvwTuZp@_mYVSSX0KPYLq@|f3Y6ey9CtTY%i3r-(ML#_trd+1t3#!RDRlmY)m zP(6<9akqVMvXM(>FuL8~H-%#gtlvx6=o?t7`h*73J&!zCJU?bRVYXCt^oecPZEjYi zjlD@2)RjfD`D!xKF+s|p)iDaDQ3x5N%{QHST&p}H&$+r zt2d5KQuCx=`&H(3gt%#?<#U;wX%%g6#{t6@?}5P4{w3jS=KtAX^+6ydEtPM1>@%YKf+!QZ^zP36 z);{p~(vYE&^vtP)??UNG-ns3rvz;Dwal({%d-MxJEeCLv#fwyu@LSIZNmYgmso)b! z39k(t6wn$F1(-M@kp1LLAz!t5A?TZk;HRq~b*oQFU;Vd% zS&gZ#%Pln~e!v6w(j-15Zs9OzDoX8bVp~T+8PbSE6>ZRdUl>CAy_N%}OCGp?@QdoQ&eUfMAf`wlGn3n7{rL|!uRv=N z@OZ+IuB7t}Q8Qm}N_5k2$)!`@H4&txG~97gThtxbZ$y}7PW5pmyxQbmtSCZ*kiYRl z>V6Xif9!3&1y7oYojEBF*S|_@8fI_(thkYY%v@h}pT5(eGtPZ2ru{^i5D_UkPRSc_miqQ?GJ7&DneF-m-S@slafGK&JMk#wUvU$4YO`ubDnn)}s-yfXaJDm;h&Ve18K#|CA1?Zisk9i*vh7VKG= zZ>>=YadF&A4>!__<-^UZ@8=-eS(7hfROidz?X%%)c|LFO>vbJfm1zyDybvcB;86We zb8aLN3g$H&c4*vh6^pQ&gkIaL+<6Z{3Z$uKFkVTOug=xPzhP9S`e_m`G0nI($c4`4 z_&?$De^#uC*i)v%T2b05%7vGTnnY3hLW6|p=m|FK(eJiO`}cS3e|*)ET*9i!M&{yp zd15a{HfxkHV2=0FDr;)2Y9>pNt^udyEy~vz{88DX=03{3V)_h(vI{}Px6>85wd6Un zT{jfYJLxawmdT=af9F&~`Y`9GFoU<{=M_VlOm$b_Z5ufRg+ANOgqC?>b=;jdK>l!b z{;_5&=pP8gvTkX6nX!_UEJ}}st3Ge^4fI|ocjDX|uhsLPEhBEO?p$`)?t2c{5N5`* zrJt>I>5*qDhc1obG-}tAYL@@#@HZfw`a;Eox%u*Egtxiw1n7vZD6L_3-i3C=O=ao@ ziQy&AfNzbFyybOt##-v~2P_eRK$oplb z%C{n8%j}1)zrv{Igg)JW)2TStxgGJ!pY1=|`53(Y%$ks!DSd_1-7zY~IN|y$Vh!xP zZ~yxk1fb|bT9#}%MeB*81zuvzw$|U9dt{LyC?C9ng4$JgATr$Z(-I>q>9r^=p z8!esP=t<(^+vNk>OaoKUxCFq9e%>>5Q7O&rjWfHb9*x`=bCy~4qjMUnBtCTRhROtr zD;{4lAeiCG5mmMleFVK%%y_kk$*l}VXZg(MY(bIw;CCgoi3db6gAt}VKVonmJ2dAX z%j}3vRcJRRpQHmzpFRh2^?R~lssC(p6*s0J-e0dLMVh=WJ2FI%uywN)A0E{fkA;YK z2el3o6h&#l$YZ~xU?;6<+jC+Y*($B|aEe0adiApL zzJJ_!ugD1_Rqwv``u2dIN>^x%F(5HG_VoEJF=pAB1$BWic7NnPrNcmDLIV8ItMQw1 z;z>4ngUe7uopnWMH>bbQ?=;}|^Qwb-^=jSK_&c6hID^s!mz>6pSnd*IVoYE{tvGb{j()-GSbO3gQXDOS_ zPU}fj#5=?k{Q4ll_!2D|C{`T(juIBQ#AL}G*X{CIk%ASJJbATsNZ9fNOi5i=vF&G; zgKu+K`ehWxvlT_!h2V8Zc`PrZ;}{|9fPgPa4xO0MTx^I+5|eFAZtk(GJ0m4Ui+Ba3 z#W6t{f0pbA#`?1&khw=jETLSZ<}!hJ?h!-7%WmtaZMO*P&h=0?uNROL6;xGql1$}Q z{i))kQyQ`&F{};wV*3KYzt+fR(SX{0#XjwVPI@5fUCiMWtVhM*l|UUd8{RueTmnl@ z_x12;=VHbCrjq^6dIYue1fX1+7+c`qw%6fQ9`i4!C9bSV&2dR1K^$PO(S*Fm;&1AB_UY16}0BH!uA8G1D4PC zOEUZCofkLA{1-0CP;A|HkA*E+<>~xE4t?tdsF{E)ys0E-W!Nm)R%soNYt7Rq(t3;+oURM{O!1`Dfwn7&F^AdMZ2r9&^gBd z7z-fwLJWK$YsLR5X(Bt?qpQPc^j6(NN?kv&^FsLR$F*r+#zdPZPlQ$q%51$*R=wG` z4C}=^U0vh`Cd)cfKPl%&fkL$u@bOw>H~sNP8xWxm9n*WZuq8ZoGos1Z2m7^5z{ri$6# zHOZ}m9CMiOBXxTd;yhvyiwZwgE$z(3tr^k>+LWdI*xJWw83C7m24Yb5nYRU>7~XI} zBR)2*yKUCXU7Wyih)|{cZG92X2ddmwWR*~%?{k~zHoWY~+h0DjccyPd(WmdcU=_^?W`W`5M!L;OgS|t?6GzE?{m-kWF0>ezsBX{QO|GG)KLc)H~ z(G8!OfN~Tl_6zL}3id`XLmCC}LGhhGA1XM50l2@@_9%Mmncf#oD-)g%m4V z>)ovB)GcNc_RV{EFJRIVma^N#7gyP2oQPV$dcZcYFF^e5cfAE5^*unhu^(DDZLB__J^M!o#)t7Vih z)>o!u*d3CG;Y^2WUgw`Su^Hf5f{sLapR|>F z2NsiVjsizKLmRZaK{yXKC32+9#KwD&UQLKR>qa_&Si<$A8Z z$o-6~oxz>hrdr$BOfVu6TJ98SvdgRZP-T@SPa6SxG$Y z`pH|!<^)PSe`5TSis>mkSqzy9o5$)Wkg!w)RHEYL;JK{qQ1<5%aD{3oxbK2dLWgVP7Y}eBHvh}>Q z+;d^763s-^A+w_iiQ#N@kLUKpi{Iq-yzP8QSD-(Z69z#(Po))aHS~A@=hCiM00 zaZwyBB*%VrC}O(l!`>!AnaB|`MuaCNA)?1h{`~N+J~ref?==yDUHG=o@W*wP*NBoU zgEQ7=PkrQ$A2)$skx~;9C7!O9BN~Fr_%BMQky0vz=3+P z>wQ4*=7>gBlPfa0A`Uz_zMcF*D-doBI9mYa+zTI4LdWLUA6v(^hiRo6!T+TtfVcpx1CCLL zPy{xv-tFxl@UQ(7f`8z6=&M5cJNPc)ch6|13*x#)k%Q!hg)|iTa&l7=IHQqp_{DF; zS$A(dQg^Ky%lgWvsJ|rI5CR@|`5MTPgAByixg|Fc0eEMZP@XR+b#ab}_@7^MwS{Yx z$8mg!Nu?fNly7=8$V>G-HCn0={J5e>;R(8@L9SyX4(!VYaYoT)AunOkdvs zW@v*l8^!Lw3(emy`fdpH(O7{%uB>v!Q)yXJ1`^iS?XH{V>SX=sc4LpbyFf1qrcHQ7 z@8(td`VTOAl<1nrT4xbgR-%PTmTfNzmVgB2{rovT>$Zo#WWk^B&j}{Vn@aEZ#VD~d z9XC?TkDK-ODJLeZY6;&Ia)sI5s{Svj&dIrb#R4x;_{nm}LzG7EVlxvJWwV${wl`82 zhn?0+VIh)$+HrosZNPE5#hX;Iu)uX@CI5_y6>srDNdJ1GD)>6zTav|X-?7^(fJ{SW%utk z9oi+ulLL|^KY!*GD?v8EQPt;icF?>U%K^^9MjdjDu)8S@PbVisrMYA#Gj{cx;aP_U zx;AXyG#Sr?U>KYR?sy1KQNAm?sP_8D^>^{UBL<+hOks8h()YL5tbsuc;YL>EJe3-4euRJ^%O3H`!7QADrD;+{OXn1yZLl zcU8ZeRvOhiCw|aww-E)$qry6kJ%t*AIuN{F+?ypH#%A7J*cpc!D=3k~2F$Ur$+ooK z?mvAZUW_C-xdmE)wkT6dw74-{|rJWHGScT&v0-%R>mT$6v>h zQkGps>`f>4_(*WZrQQ#Mm(oNR9cxh0XNFcJ2stl$RXnN_I)DLTj<o9MQT_opB69gMtkQQbz6J}or2XR%!Dz4^dozdLPz1AVq zi}ibhVKqKh~gGc<{^m3H*_-W?)FdGADFUSRSlyeq(; z64R7>lL}Sy!6lmV(9b=2ymnpo@h@81@d1KjLkcRqDIveaJ`V_z0gt@pM>lGefH-O= zeX?^CFR@qG|5Du7p|>7^T8%M&;rV>b$al3~_7xrRl;LIMx!WrYIC zH)jA@Xu=QBfFJnj-H3mR1IWBD_Vyvw_iKV7 zK_hCc$eLP+m!A#A>3ntyd`zT`suXKP#=`wM#bJM&ZpIO7?L>yP%qo6O9*}MCQd8W; z8Jq9K`A;QFxvPdr@?SfICtu^)Hq;f>_NfL{joan*!fQ)K4ytozwsWX`8$pW*xJmvByo**+kx2NoQ%m55nVF@% zc;7%c*vb7T5x~=lR@?%D7N#G3`TZVFF!6zi0;VK%23ztNknCm+h?9KH-#?0zvCKB% z`7ye21Veg;SLY=G`GHw?&-UO=MvPJHwWY5XW?k6+UQv6)teAEa=`A^Bj2dItAVoAo zTUH?Pn>Zmsx&{Boz>$aMwGq4DFFA<~8_4dopc51E;S0nxHe$=Un2ZGE zmhC52P6omzNqih1lxe53!T;oEviHJ#Ju<+avLC0@)OS)kQIv!s&P*dDJ*WMy8MqhA z7|}r$Z_SwEp`pAH?9}pO+lX9P8r{X2?KC=89g}(0(UYXwB@b4>ExQyKlyNcoIjjpJ zE&0VsQq%W38LuRsewIww4}125aD&K~SAvNt0l}6u72K|WY)}7w>EW<70-O+mKaCC= zwFpvG^6*cP_rl%$+>F7Zy~m@|G%xy*OL1cu8I^YM4hQL;mAr0HJ8C;3(qV{4+TXcV zQce`3p1a>F0(^)$ttVglO?94Oy!dsg2yx}kyyN+fLg6vO{0kuiFn{I9ZjXsL1gWll z$>w3sC+LFXb)3b}2PG85u;KHO7b4M<8_|kJUUT7ltU4}A!9G5p1`{(hp%!nZNjm;`>rWO_+D=xgAaKkS=XW#jM$q#G*+WgcjNPwf`P9wrD z0hjnc(8i>`|BkXj`Mj+CSX zkTOrZ?C6&z_GTRQnEl-Eb|;J;0~-#FAVas}d#x;RcClIDtM-mEvHc;)RK}EoI8sKc z-V`}&-hS$agpNmsFJ;9nQu#MywMbl_qLC;uQlTzMl)v7Q5aYa|n5Et<5KJ%;OlSt^ zER5Z6YX7uIqzd^ZUH>tyr`!iL_$4vkTD~kXEGX^>=6WM0<|C9e8j_i$StH!p^hEtU z0N_t@WRmoehwp|0AHRh5b%iSN0#|?e5hbOWLUlYyQkwv2TNkr>XWp>EJ({sp+E@M? zr`H?O?)OqJ^z94eq<(>%SKvAMk3R=|naI5mKC1(BbLzxlXwX1r?yvF;cj)fkC~`%i z-~6Kdehf;I?d4P3d|hqaidh@vAdL%;c=3ePfJAmTo?TlRy4ueM>6jtwMlQqHXMpgj=s+i`-=!zHrU<11XDjxROog8 z(2cQ`oR@s7qRCTPI=zN|Qu=3+>&a>naWZ%u8)lf>E1#!_!KUlSu?1F#$IsX720J@v zeM%ED`qt%d#K>Ml+amG>XBKk58aqM@>4V`EwF+@1b-+_`uk>Xb_7|>P%Gc$7O0(@h z#p-muO7w_ehuVoq3l`4N0Xuq5B!W~ZI0x}|CfEQ+Sa^i7(^Ie&&t7?7RTp!A51R${ zb}-b#CY=xyOSu(&e1dvlv8zHwa+z@+NCiZ{U=J57KWOJ$kqvE=MJ30oh02AZ6p&Q~ zxCaJhtE+kY20nez`)ILd@%{1$NZk3RPCalVt_ zLg-YUe4w+K&iY@>p#ci_BfT&WUW8u*E}IpyW2BzJ!a4Sj8&D;$N3{iZslpkFQj zEio^955s@&Pc=%U?@JN{#S$IPA3cl`4CoMSeG$?DFYb3Snzu5jOddBz&!n z2IXSE^5x&PfGES~TIVdYYd>D#=#DFkmLum~Dw6QfR+9L(Yg0}xrX^l}h^&9n88<{h zE)5VJ>ThUnt|KyyNZkUFw6Fd5V=F0EkYAy4V6A&>BtH03A-5t4ieTxGQD!?u80W+? zPh?Y9CI+?D*uE&7wtZumpTxj*d0x{D ztC(-k^}Dv4z<4JNGr`xu`O1|SUCy&XeC>SgaEj>{BBVx<2>-Tt)VHn&`~PYIK!^fo zzE2wQn?1lMBcQ8ePWPS9F20VI+(>p8^rn-?Zl6*5H5^h#32Z-zLohvts;U0A4Xq=a z4x4x9Mi1ALcAF>dl^4aSlWwJ_B*Qy}M&>!Gm^3cno>+<&tvr(=&%KOn>YS+$;!(#>a@-mI z)0a! z;&}TB#YL3No%UBv+}%M%j%{e`{(=(Db@c&+e_BjS+wnNn)Xg~Tb*00C-P-9LI*mkL zoLrgx_g$p-D`LFfaA)Fz-=FnfHODw7UAnggzx;IoVu7$N|4i8lAni4YAVKs zWE*WNFJCJR)!_+kpU`lHw;a@$ce?Et*xsFNOt{^ayd_oK&_jmQ|B_4FxU{AiN&FNN z(+07~ktzkfJN$uJ`?%ur1=olI2gq705F_bU0`R}6Om#(f8 zX)dtgCIq{Mx3~OWMvOrF_ao7k;(<`wx45-fRSw536C2)GKLz4GWvn$oo|=VB$f#rPsN`SmAzr;fNKdZkI&>?_nET3bp@EC5 zwb#yiQZt*zRf$#;0kGr%hEq%2@gbHsNoP`7R3-C25k7#d_kP3U;W20dT@5 zo*F%|mm~aQz;bb=%;&>AYS-I};{Ad+C0^3a7NBI6ae#deUOxW)zX)B1o)bOfU$G7M zu@SF`aQq2eNyoy-m|_APBu7^owR_pvVYC!e;+(;>`QMBH)^9@o_Q=4FrlZ`+VYG{k zC@KwmaThr9@E4ZL;Wm8kf}L3sgx*xlV;(04R)n>mnoI#v8))dHqd?M08+-cc#9$69 z{Dd4ru0|M*ZwcqnE3F21CS5I0G#II_Sz>W;YT0ysuk&Nmqe?`RZsPgntOubPX5g8e zlRr<8?N0x^_e7gR_e$yPCw0zT3vUAoth2z{WmRnBD%JtnL4%R#RFr;@y81FeN)KH_ z@_3Xa&CD4`p4^@zvHE#M)c$-8<~b~TOI!K&Vr5AGgsoXy=)L{B@x|Y9f;fO$B8-C@ zP*VXpt{P=(){_4oE0&;5NnFN=o%`W>#6jb_>5-qR&PJ7o=RmVyXLI_&VJR3nwxR5Zz9#D`~;$DOhSMo9)8E0Ty!0&W73QWudQoM#XqqAWW99VUA()r|W~+ zMB<)zB|f(%v{Uuqzih-5A7-u)iSv=TazZW#thxM++d>rc0+XQ7B6!MbX}kRX?88k5Ko7^ z&4`wr5LlbCbfj^7DjaLoP@3J2f-i|qa=27`&^g=N08x2z0rLgiJs^&$w@YsJQ>?X9 zohevk$qE4`&6qsWOY}M~$n!fUX4~H5+;H`SP}uNcF=2wL>YDOs-9pe&M`b@f7Ri@_ zr*cF=GVs#}kI`_vWUx-anzb751p0s6W?%fbB* zQVS4JM4U?#;OlU+VQdwQ$ro+7!Y#y06L<7)lUAR{yJ9=quvA)<5Peo66(R81JfqR- z=c&BMx6-Wp+={P*GMun|fZE{TZ#Hy8fCy?9`8KDZtm5v-J1<#Ka^{^zSU@$(MrXzV z&<0aYMgl6IncJEK9)BXX|FdXfaeYxs-HBkQPk%(99t7A@XtbZmEDVRjy5aRtXU^-^ z82Y>yLXLDrIhX5S=Fv14*;g=1kMiR=@ZmD!9^ zNZPT5eO)Y$V#Pkd=3`gCn^O99T`gJieK2mkB~X^%tDfV-XmML`9JFpdpd7Dv{C$7> ze9HTq^4IpnllFg~T%R*UIk9*d)Bi~t^ZU2J&io=F@W>caS}D^C5uC5mD{xfjr;*Kn zOFH5VNopLv5sh|rR&D&NJ;a*fodfV#R+IoDwc;mUNf&|EHLJIM&?vA<$Se(g?fa#j zokDzT^w&8Ps^QF2^35Oe2$lTYPNXQbq$z=VjstXdz4HEP&M9n*eZ9(A#-?8rcY9WD zBTi6mk^mGxFo2{LH#Web89FTJ*@2CU+rz9*P_cNQx^Ju{IUaGWqH7JU(!{%@f>OSEP21_$#ud{m8QECr(%)K6 z<<{s(XN!8&DD%Ct)<^Knc)AX$jgoeX;sv>4%GQ(uM_=}1e~tK4No;khy)Pp?E-5wjBDZ&jgnj>@#3k zsbms|xx8!Lu)ZH6_Tz@6QtU92D;bntQc@^fFW>#+#;75cm4>9(O9v&8%;WQm^SUAM z+XW5H9-eHWb#1Cof9K?pmq!c>sZB%^6$x>=*n_AE8|n|vxq>X!!01h3B>K~<@3`n3 zyWWioyQ~7IjUAq2>o>WqdEfg64)ZybpUJp0qS~XQR+pZEdk$@nSv(hdFWs~L5F3#G zmtj95N=bH9h3&mFKZE<2IKbDSG@|zcd8-k~QixeXx#q?5#6y>}pfaISO6%`Zq0`?} zAoFbdv(6Q7SOZ&ipN`6xckW)42|!QYocevEi~@_zeOUNw=dnm&xDR0GUe#qo`fKv3 z!}I!Of_AOrAVeJhyWKkvM>@MpFWZv{02)bTsr@t^!u_GnLY2HfM@;| zVzK>Gg*=0nO6BTmsde8k6T-fMWxzkRU2{DtcXDn9(61=)PzrG5YkzCw;p9DfEDz^y z9Cuk^T$Xg7(tIhdtJKK@*q4cbHSx*H&5Dha8)fY;J$UPOG&6+lNFo` z2hTw*46l1Ry^9m197Q~T*Ndz4|*XBMzCD6(B=NN@TlG`qu>zI$o1@6 zuYTjnM|seVi3viHGFkj0yeZ%>TO3wTe))QwmBXHf$g(O14@=3ZzEnooOR8~_;Tl+9 zohY~tAFGcFD|m8BTFc@c+1u-d6FTOp#T_nj3Qlmsx7(Ung}djESf?~6?G}9!%JRv` zE=g*g?vdkK=jg6{M6Qn-vCl0Wy|s=2;fDQ+59KD7|2B=|ct2K}Yru#P5*LLC1_vD)@R;JN+=mU( zCWSAEH%3>O)}a>suu)1pV1t?;c1xXxoOM($?xo&^1!3yKfgoR}9M0Jb)(iinpyZ!% zdkjS2ZH&3Th9>ZVRJae4JlcNq$iL=5NDxi}jQ;VG1~MUZ){j2Q8IFq|E6wSb4QhML z%jU}7-5jfTU}g{lpM4@W+0PCh(n~zO^zPktrJRVW#qJ1%x~Xk(frNOO{Tb z#NPM5Ki1#hn&*B+y$AT@;u|-}+e~baJ>dwCCElJ6caJxFf4n03M8(lQNFcqHq*CxF zoFozQ*|B{>$ZJ(q5&XrIx0lo&3M|3|l&D1Xc_wkFRC1qUiBe_l>blloLwoojRFoD% zF{tOvoGQ{@+OpR!8U?Li#Ggf{v{@L4jC9ljADM~_N(MDbQJK2TJaRtWjtlqvVgv7r zi=sxk6;S8tVS+lg&I8f4=yHhq?H!3fRu<|#b|dnA#LuHvCR6uTHN9baWi-0uFLcAI zewfQDO=$!~AzupoYf0z5qbMELTvus}=rpR7a*ko}c7jmsA29{TLg}vuwcTM4%PP)3 z2-{#FXk3YKNpDO7a5e+qKoboOscS#5U7;33;Gr(m;JMw|x!K3AJ)A3<60YpuzvWmgr& zbPFjC%OFHG1&9OWeH+%7O+-Vm6hsW-22jMMphN@~R)>zo4%06l1pgslkq2| z!7vh5;5dJQq*#^b+iPAq7E<$s$_SaluBLhd^0kzb{=9}M)1ALj@ZanDGXL2Fp!B`5 z1OwiQ=a^f_#WVjsx2D77U@PvLfQo0n+oeI*-K}r28x%a_Nb32BR%jn?*Rw6#-L#ju z6(&jqaxE(>p!+^S3`1V;vFZ16oIB*)m~iZaefCOv`B=?Lm*V6owuPyw>Yc^=ewA(3 zDF8PN?6nA}s{RL+41>?qhV^I|!CUaO(+i35Se4}_Z$v?eh-U{@>E1UOPkChBn<-X# zGKWA=O`eb?Wz~C$!H|*A02EJJk_Y0}ZIu)Mp@%#ryEmX!3Ah{0P7dSFj!4oT(E;xa z^J>$Ge=_6GrX!dPN;K@d+A52uQfv-~a>cGt7Xpx(tRO1IM_*HjATQ^|XkUH}>HxJs zP%krT6bx_v*6Jq)vsAW;WxeB}QkTE6zHQ|s&wcj)KPCy_w5xTZ>s(LVnPGFW;A*c* zXcb*JM|}`o2*Nn$LloL4CDvR2`5tPLo_({ECm)Su6`ENfw(OJO-vkQT1Ww~qL33a> zb7E+)T1X|%a&E|&~gJS*ErMMH%$6$Lhci7D~h6mDdBoX(|o?|J_HWTV}%a!INjy5QH3(*%Sh%e27c zXmM{UZHJIKE%_Vr( zfS7n$Kf?@;j>sZu`}R*a+ZI1*;7|TS^LaayZi;Z?C1a=g_^mdi?J zu%S~Q!Q5%TYPnNB}Zu!Ygw-WSbZxjD0- zh=nO(R?2E^?P+ztzkPHB(V~jDra*0AM(G%W-wnWCS~+IYhY&ZlXWY!+q^!>zyU9KN z@5f^gS1#J(^ZB=**{%b7FfDNdTD8t?(RmU zVF_sj>F(}SI;5q$ySuxkyQSe>pa1oK;q%_i{ASKMQ&bWlMt*3-W#)I_*`@?N_s?yR zmA3GFnVWd;c0fUq_kOFsDlB$I%2UzX8qF`)8rPO?zoSXC*no2%MYZI=m>Y%-tv^6+ zGcSz|Zo3jfIev1tAytp0JtuaagIfqW8q5*4Vy6hJX$C$JHXb;*AJ7t|c}N!PL2dCs z;Y*J1%62W;TdHOhYb}UV41wQ?*|=_f;EkE31U4tVv!W)|8-3fSU$sX2g+MV+(Px?! zo?2nJS~iM)v*L?DH=AqGd2QfmAkHFq;qssXVx;=_EmSr<3&tSpluYk1tFB{Mbdt0M zYiXx*qqw5YYMWlHfHJL(n;Cn!`H(#GI_te-@bq&R&^$FHJDn#=;1Q&qJU- zTQE-38j*dF+5Fn0zFEbU7v?~jzFfLdv%GQrKz5X4MWxcS)j9Me3LQTn7fA^7NZwtJ zmHBeXjb*e18>e1VHGz}STi+->9g0S4XOv?%blK*WRh+EZArio@il#h*0=wN(1;xu!l!~4x+HVK49X7i@Tz9#fGji znj6VjF#8!l;&l`>nZ^DuEJ;a2hQ2Svx4BA<_P-+lhz7DtF}nAYhGV$eI!`tK1ULj1 z`4(fH{BS>69@{!-=pcs=HBI>W7$octV6&A>V>O4&_drl ztqiLhV3UewW}dIL;8UGr0YNP&|oQB)-1H_?Y?c!e~%AVg5!|jxid%F#`;)! zMV6*xFMVZ1^de5m5+0uD@I}?@ejR(Qg}H;EzgJ>Rpkflo1kYd%R%r>K`VkOQK zJwvBp)5op8n8?HQzNOxg;P03saCY!$LmGl`oGplQGGd($qP=G1-?}+1kVvz2ETNj{ z{4TrGaFyt07#1|vVN=s&W#I#KOrObsVQ*WlpJ|hb1AQkV#S}HNFE64iG07$=1`6hq z*4+(;nqJ65hO+)kH>V<B`$&yq>oc8&_45GeNZh4jO*Vn#*imlm^`@DwFf#ZW67HLaxZIQ5Zqnoo1bzW z2j3Z|>*#CGF7E@Az`e_qfe9dl_0&*iR?NpzJPIxC{wXVQ3xds}IJUHeL`7(W2CUP0 z)cf;#$BHpfD7b2jS(=O8j2p$E=Bwq&s;}5=9($6nEoJY!E$9H<3+V$Zt-Isra$+0$ z+gB|$CB~%x0R5hyulC>8jpQ~nZ^}x`qA`(QxCGZ2>K(4b2kcuS2E!+64l*`R!Q|HxNk8D3JwF6JaS#D4~SqR_VCgnLhi3 zY8cH-jUbYW{Cjo2U?FA{KLowIktYhJOEC#q2Si}<&AvQx4qP&;7_f=fY-%d#3jK%n z5z&}H4b-)u5Hgt-5Rr8`Ct3ck0-gYagC9Ew5r@TBDlyECvD8z#2lk_>3sR#7_kCOG z@6Q)5e?vT&pMR|1MciJ`$`wn3p!3GCgzRBp6_?j5znYE(8lTt9`VeMR8~};vCV|dc zV?p6n-`C)BOOx-C)(#X*7(E`${u)LY+b-VD5%Ate48soO$lTXMn#5{zleH5rTrrJj z$Eq64xFA0stb^y2PGUZKGAndI59-U`kb;snk!X&>RI=20(zb7U4EJ4Q$cC`Ny}zQ( zz4CWR45|#Kn(>BG{&PH~*v{d?Rf3JU^M7^2%SZmwTj5@`uc{U@Hb}D@4=8 zjXTh)53jqv6o3nev8UV+QrLK7!RKt^QEkI8=Yc6(!cG2(=1J-38U|}mVe&n*@qvV7 z9owQE!<+$N<*?f_f6MafP4+QQ=R%epQvz~kaAT;07B_|!_v5dBil&$qft3}(z+!fC zPwgNY>J>zJRkh5E!sf-k6(bq>AFB(B_cYZ9q0ANPb7D1_7+>b=>ZcC{nCN$s{)(p{ z{gcj7rc5`PFwBFAD+FY4llzC(sI&2eoRIBHM+vcvccOwqAT<$Tm)M2f-#Yk+RBi5A zNsXqX-?umeEPK^Vrf5F4w&6s+Jn8u7*k;X~a6*Arb|27`DfIn?bRGc_kk!uh79n%p zsKDO+A2*dsDpk7MvA@%5oi&c>eHo`rXA;;M6aG*P>LdwaZ^a~vEjO}N;+&@!e~#Op z6wYmCSKqa-#7L(6_br%-o{S`ZPqpoy1CFhW#YBk%GrdkmmN=!3NyAe+Y4C8H#p;o8 zOwP|2zR@qf6#UAysQ7n~NY2inO=~_MW>R*erlj*oXnrA)6E1r`P%B}aFeP_zXnPx}SW`Swm|p7N(ap)rhHPf({J zh@k7&2i1!|YHA@5CQltCX%S#`Wy+H81~KyuVdgqd1|Ka95im6iXPwMS4}6*|o<5`N z4X^a|PWI)DdFzj&Td+|7a0dMV6+?G<^L`U6f+-PR>3u{`y^r;4vL3hzFxI}y6Nn*Z z0isC=pY4cE#og^ibsmh4E}@!pSN12Jd&DmHorNXWsa}7L9#SN;G@3}kkd&Y_i{DMg z0SexB^?7|Y@bUW2<70D_AOrVbHpj!N%vkTzwJ?st!78`o9K^$iMbt!5musaW(H8qI zki9&~LAJ2Xl{x#TVCXPNH~~Z+%=|%1Q?Szm0Wm#vzkm;6!V-(M_zTF938t~n#$co6 z#sfF-lLu+$O0lq>Qn#F$7gRi$(I-LzYaz35!P) z1f|uJ@W9zW`zQ5JS$|JE?F`=uhklPh&f75*Pxk`@kaJye!OJN}#zLN7ybh)#ZWjZr zbXNI!+Axw`02iHowXoPxC??PD=?b|M@t^&W3)4q3+?NF z_Mn#OY{h1+lzZ>colCVf+^W%$jZ5F|@_mB-!0GAMpw&`DiJ2A~peG7xQeELp9C=#~ zkuC-`=P~w~P|Act?}J`!mV7$kP;4taYAb6pi(hU@@g=}&c{pMb-ax4Jo-ZFtDRgx; zr(5wi7a%2Pb*A=ENq<(7r3ZjNhE*H>Xv1P_QTpf_1hS|Xh>51hdp1TMPgBbfM#KB3 zWYuE(NffSUBP&VHC(K(J)6FL+!!3T^j4KKemQkD1RfO}2zggs(_el6V84(r_>-R#QkWJvOIpLgcsqoR(7K8>e3_uLEoxRV)A18sfpE|MisvxWR zKe6|k($_EeI&l$ocYjlkTBK_Ac{b+cyhMEwL#d_O5frE^3l;Zc?lBz?NeEgY^1Z!d zz27)b^l`$iJly}v=w6@rr`9-saHUyhooB9NY^&0Iuz$psM*Z)dKnd&YvZUcuL?lN7OErz}ls^1kzsPiS+%bpR8BG$RS8U()vD%2w7g>DO-6B4q?h}Jg!;<## zj(H_!W}^em>rCm5+~br!us3#5e}U4WY)SAmW0MlsYp`VjMCr#9#}3^g5hHpfw-hhy z(Up`>ha#pd;g2gHN?FOY!dZ5H*m8Fee~oW({B!$%C|0sl>+dwWM3d1-T0ROVaW{eC z4~Q~j!hjae5_uefwtKOrhwq=b5y5hV3jUVes3drhpBs6${EAv>%wS6wiGJlRlAGG7 zSPunzOT_02{U_5h1Z|;8M{W&hl5*t-q*>qQ8q>=$({<*j$dE+}hacTCBf)5_ z@fE@jQT|_dI*nJe+P4~y24h~UZljW*%-oF}LbT1lFeoXExC4phrior;)y{T*A*FD^ z3Ny|B7gbOIQcS}>)ezC2IH?b+sdAl2lqU|BNSz+F`g~url!#KH%(;ySaWG>wO2Z50 zF;ad^%Ex#`vy@xxr%oZ3z2nm0^oabM@1W zoK+WD=ron0kPn>>T?@`kD1!LpcMn4qg4Ke0Q+&to!izC6QYu@de{}@jbYE4aE7W~W z0(Ke*u(JS%9osk%x5fn%P_+X#8;(4Ak#8(Iny<^_PH zTRDosuyJ98X)8mEU25u4sP6`G?z=YG4nadxP@fu6qmlKX=)j?pfA#R*0% z>`zEjdB3GCfBxh3qGV4duGIZiBYh!VsyR zm)Y2J?Q$?WbQy%(AU!)uSX8B=MBuc|_)qV;4`$vMu?T}{{{_2Jj01uFgm2^IqX`L< z;@BdpoVyr=eUiQNL|9`W8O=ngs%;e*M6K{TLnQdOV}sjrvh>U(Ir5hSW z{44@`QOBi}0HHusRk1oBF(@8;m(qAdzTmnc{(X2&(b2mL`e5|~3bcBFJBnTeLC>sY z!0ZmlN%@1%BCDCp&%Ip5;_Xc!4o$l=#v~FSSw?N?{vpC!UMuB4W;lok<22j!RyIt8 z;FYA*jfDzoB+~Syi%zl(nWR%}{x!nt7;LWQ$JiD*x_ml9l)LXE6|-*VSzjJ}Q@{Y~ zwIlmj=_tH6r^sS0{F%|OQxbVK*DgZVK0Wxh#e{k85MN_?<1dg?Jv>Xx=zT8DJS*`q zv6yXgPa3AN1kHS`>NF-Rgxh3^0e0IdFppt)Tn$!oIV0iIxq?OwF%!^RD*M_D&~Y5` zJPQvzLpx~g3N{EIBX$;9&K7xZ>mL?$q-wIWtW3A=8*2*AygX)FgQ}35Q$VDo{bvtr zu#D)=7$H!TjBQ+HG}VlW#fgCK5urF5}mRx4KkoRPTdF-Bc^TqaA$S@>QaO5>qV#9d-S!&Mm7l~Lc_Uau>H0H=)ZM}^H_i#%^=v2$e0+e8OF*Ymn>@XXN*+$4@wOWLPm7Xid@6 zqtIJAj1{E1pBdj06Z|)M2G6==%qZBX3Ob4|uGnoN%t(?$g!{Xs2D#78_O5OwZ|)Hf zmB=|jFrHaJe~e@nfDl2N1wSiC#sruW#fRq~VtJ4qGCRJ6r zYfe9oK8GwAT^7Z(>yo_emGC})l)i2W^ljhLEWOtf&0agNaKslEuq`Q#n+7N5Ld&Qi zT|QpdzKn0r_95K$O4B)sR>HNK2uW6B z+MxQ1#l%?O;;poEV)lSdH-m~SFThS83`=~y{L2?E%mL3i!8&}Ex6Bb~c4Ol%${v+qa zF8$FIQ5Nsdi6Jv+jFFats2AU@$d&TLh0=vONY97ukVEkUWY}o|-MlTY$t-TUMiDA) zX?1iX&vvxk9^S>Ypyq3B0P4l1_v3M^O_LJYf#gfDW2F9I%x`ao;yE_T)_o=qq&D=4 zt+@H^EcwL-P<`Sb^x^%dp*Wu-vmo;H;NO6>s!7hE`+u15-K`7Q0sVu|C)pRy0wE0 zT*-&bCSwJgoh)zEm7VFM;-4F>)kX0W&#YIk%a8uPxuA|rhQhwBJZ^BZM@$xgg9SGA0Ajhzn{&d8dg z`@Ke?qnJT{jA-^8@C(mTJ?idNQft3qATITv;MPrQm#3+bR1cbBfe|QvO5QDL zdFN%^mM(Dn$WU;p@KGM2UySlH8+q$Td5cN)lKkjN)F2P6E+-uYq?N#2+hYG#C29I8 z)lI)x=RXc?0kltYcug6_s;0PxEryLG5lQ5y6^J~2ejb$=WEb$9J9J+W@+q8Il=El_ zc=wUmYTTZfa>R084pB>SsO_+#dR^%->z@*sHqzwNOGwMkOa3ccFPX%GkFiF0Cf0XJ zucRHp%FXq+G$uePUHGpV^lupPB@kr&9({r+qT3sN-ChMFfu!4Eyf)$Dn2)I<84uVnr z4ogblx^&TPSNMV8X_@Tk6#q?z)=^}6F$&mhdy)s)Uz_an_#O5^@EK37QWEIm*a>i}rGk*Ft+hED(4YBeBDB^>Iu z$P$}HnccK*Ods-_fSb9Z>5~rAE*8sH{54Hx3ClII!i)l1ZPmz=6)kn`o20nkrgKE( zj@WQxF?$_6kz$<~Lf$0eTxAQ}P$ZcOT2rKoNT>ej7AYC*J@+Byd#BXv^XUI`gIEcG z02s|_>wx0nv6X@y6+?r>D-e@;#-5Ds}3C0n;$Zs%hEu0nrPjUi((AS-3 zSm77*V#TF!W=6z1iasiaGo>9NO;zE@~oano!%oWI$rXoBdE6}y9dpUyeQrQarht>|DV&Yt; zsKxfTk8!9xQ(D~w!*AVUai|et-{aayc!dK#1WJA8f85%zZ0kGxJ3{|rO9rU9Q-7*0 zOkrYkM4KYl`C7grKd9P(;YtiBx!(0!wpAW=quKgJ5CX= zRWPy($&T_gD>@TkQSh?2c7fK2j9m2ZX4}?Jk2_ZR*y?DY3uC&#h`?6QNH6;BoTl=M zJ0$tdmQK{oSm_;we`&r`1hJ@nreVpe(12v|Leq6ole?rLa20}6!^Vc_5&XSsEW#{W zncGf^WzA>3p40X>dqo5&8UD*(y;$p@r$NMX(epEhx^@Lo>*fPKW<47Lzil}$vf&UF zVr@*fP**kAZ}?bZe@d~Wk98K8m{^S?ZDYr)83T^K3%3*$zM5ps%ki~nOg{$w<1j%q znQ_;r#S5>N{N`Tfnv!;;wM2sOE@)tFwLuT1>bYaIM-ex%e{Mq#G)24-IxYFuPPQI$ ze`{DK{^?TrGf5)c=$B7B;;jB?>$Nnie_0HYMi_w0e!hm^t-<^O)%vwEKaiw7TAs}J z>wlWHwM+|vCl!H;3?*`3ejsfu@KPCgm>8W;h^i`4`ZKKcqy?VN{z0=sMhU~?)KCXL zz&FyO!M(}^)GcQ@YqI1uG5!0^cm}?T{4cTd6N`Ek-y#{q>Mb8{0~mbZm|uuI81Ok> zbnOBE{>{ShprYN0b{={GH|zN)j1qMDA5CAV42iPq~6vtI9`M&cxn8#)s=Dj~l{k{`oV#N#oKL#{>+~RJfNl?RU}lf&q?&S&YsI=#a^YsT>@YQ2 zxx-x#RnY|3Y{m)X4sF~G$yriz$zCPZci6qRCHJ7Bco5k`Mt|RkaLsns_Sm*BjAi(R z5`0ba6Aj7lFZo4Y>r1YB^z{f*s)-gNuxKk5Zf|`GiJk<1 z3LXn=@TB+`Zx4}q$l#y}QBLQMef`YQx&$;5mh;-?h^$wIm z-k8h>b4#s7(+uFrOdzMmC&HZbM--ZEujJcr*02x zHo>-glISvr;1%=DCPKy(vc=aDsED(8#4u^NPnK?x?sdAe>GYIMoG>Htk=o&lTE!;Y zgOTG=wb7d@TvaJEvo<=8#h?29UNx8Yp{(ZPAQh(-tkWo!sUttXcfo-9c=3DK%jMv= zpaLZD42MJ|I^l_5Z!m0YF={vjxG+rfHFXfc6}&d)%{aZFUhKMhYkFS%Gx>#9x57P> zbH1-J|5%h98+cQp7{Y*A>nVUPCc;fLKPm=;WM=yX|S4<$kw(1a@sR%;I7VVQf)U*(5g_e9nX;ojBHW#BQDMO z!cG(5z-go1qFbE9emhdN_OCj-_B~_2?574wWXnoj5;9wG$z&n1s9+v3kKbfqVI;oF zQn9jckc}^jHt;ZpK(bPF{Fh6G=5pO#(Y%hwL6_2os9FoxeO-oI_`o2LMGY3iDn#O9 zdMnI3{8t_Hh!aK)4Az0MXB8?evNJ-zL?OSTl+R8I&fS^HNM_Qz zzK-&a-(f-Z92gz(i<~SjY7F)Y-|)oz&BQQ<-T5k$#7fY<5vpHkA93f6HNX-VlZ{p^PF+0QwuFfHJQC?pEWTW*dOZXU@fX#D>Zp< zES_RF0hU4;EA{Tj!&<-mw(6^9iM5j6F+h1H?z$8;RLBZpcF0jK?Wo#d&gben>s(`9$PS?qpxjxbFhEgst;vAXD7=aZ9eMfdUwkzFO;HR#P^Y`wYseYUspn5)dNB-c_1)>`fMRN51X4-nd z&q=6t8(3)MYPeo9@J%b>QeW;aPx~R zCpyCW6EcsL4d<4Y-P?vB4`$a-t<+jJ`u|{?jl6I%tvYgB#l0-B>~k+dLZ3YXD_Shc z7V~-RKE50W#DAh9M63$4U~FsIa$rIK*WL3%%gQ~L^vp-;&OfDNL-4xre0N36B4ksY zo&m1yejbWaJ4$OeKcu|Gy)mII`49-%36D8rc#-=0_BhkP3!$w%{5+i@3=8gP2v_8S zBkVq)u`s)V&db%tML=HF525KcaWIq=-dlZjeqmn2{!Stkh0@kIO1){|9qX>^0sp)B zEiBv^DbN<7tLWZP(P@F}MqMEspP)lr`!%J`E$n#*c=r(6A3zRFRmgtJ-{**pisjCV zM-LE=6nJMX-^(9d>tP5>;ekq(nYg;Bl}q7)Rk>%3DV8Yo%#wxv*Xy|HbRE~iz!|hy z5D;RE?+Wab{?@xK86Tk__9X}w_uFgDiLT6H7{&oHfOcp0ZvF?7h7RFS3~%9*&4%ha zy-X{%TTT2vF&$$~U5&QSf>^4Hem=-A;GY=UwKT{VL(Yl=tau+qLEB3Xo5eb)Fm^=G z|A+Ew8xsQ}5FTq|lztD}FWz%!ju>dWaEmAC1e|jk1-tJQ7CxarADfv^v~=XdGkZB% zn55FL+Yf7Da8CFE@gC*(>5EgNyADn(oQoM+|Ysd9); zRk&A7%Ng#{y8R+^if_O7a=YH)@v$H-q@@{3MXMRfbyuIoZ8bpMGOOG5pFupY+*LT6!KbML7)L2uhIQb%wAj=qioN##D$r%uW zsF0A4XdW4LCBNeepfZV#3O(7M$PBaA3LH?iMfvVzA|FM5LM$ac4Oy7{LNqn$WoM)- z$<7)ZA^G~M6U9`~C`54IRioA*MgOmZZXI#w(ZCfB+~Z;IbIpV{VaiSFB5!DH^oPw3 zavjJe?5fFb+OMhuIAgVHp7om6m)g8Zs^vO{la zVPvG#!#fAxi{C=F0edpofx-)zi;$A6vf-q5gUH1cVOed!kUavtM5aL{8{7ACU(C1# zag3yo@MeUzy&g+sCo}#hf3`0J6Dfdb3Xm2uZ`ayA<}218n$pgOoqYZX#4)J6(3&`% zM9sFtyIjU#du>zv+h)(*kz#tAnSk5Px{159*9e9-fvkt%)W^PHe)e`F2auIV>4^oL zh3iXPkT0AS0NaHCXDd!x1?C+0LV0AX4_^F4v^$jhIOh}kh7g>s7+jgeH-HCK|8w`m zNmK1c_MmOoi7$c;+K4Lxi~j5a#%ZAQk8FHx3BJ3RKLpEn>qIwVWY1vIX3tO@=tEx) z^qsk$e#6ynTV%J3*CF=cy55>>eb<(ju~_5s&I3ID<0X?I`TogTbJS3bdRUFyZA{W< zKS+Z~IClqUO;LEMWA(f<-U4g+0>Wn^Mxlhf7(1x7VS`lQbF+|g*664Rs%7)zNXlgS zON54p2xXa@PM?jq<>w&;>wk%`9}K+R6r+Pn>h@1B4-VM(d1WVb7?hIjm@!x6DXSHSwtKC7dr*lOK!w)7n z7^bMOg}Cr0T-n%2N`3T++L5gVt@@(#@0J}l>h|Z)TyNWt?x}r7=VbonjawjhtCm(0 z8w$5;v>{O>g03rmomZDhW)#5*$pv491t;COJKZuK|FU{U5xeMoq7*pG*>ioNke*#isPMt=*SSZmr^e}U z$B}bX{`=$J0~}I?2+t@F8&!2KhCcBJ{GM3uQ#ZNRWDIX=2@t;^j6RzjCIErDQtjB~ z*?pk>ns$4#NGxr9pwoB-F3?@{U~N1h1S*F{rwey2?CfRq(zURcAJ=FwzfQ{X`K-q+ zEb2=gOEmm({;8NPK!25T(YH9f6~zGA>gFh{pN!aDD*Pml5_Dg5-8_Kf7IA~2@34(%w7Ei)j4V}zR)|10 ziaOYoFyDnoh6O}^M22ql!r3Catlf_v&9>31u_GB1g<#Z3fs?x~Oesr zZ#CY5FdF0mDDy~0^7`hZF5(__+s*Y?wZh}{pqWKGxEn#sOEXCBwQ10*B`-KsWq;* z%fTTxMQ&(K9J5X8aq<5BdAp+$sFuTTn_(B7Qjj?`$9pFg)EBh#1t#qg$vA=2O_3Se zaOjNpk##Rf8qn+j-KK4E6mMK32c=L;ZS}<-oV!N~0a4ATqI}@$N)tm8xD(|{L5heD z2iM(bgw5LZzS4E-^0WT@t`eJBjAk{?qX zvPZ3H&gQg;KBkvpn!7z8`3a)4#Ej|02z*i$Qc$jtE-_l0ZN$6|^*9AGzTV?x6OevC zeV+nIKYyW}jWTFYz(2m3fx7&L}L3*aVB@z?wn}DRL%5f03Nm3a1YR9$jaZxMp3%PO&!<9>tSBkT#y#cHBIQOX=2OR(x&27On% zxvJ*Nkg3ZCHU8mH28K-%1#mC!-H4k>Yx1g;cY%XHO+96I;Gj$lu`6|Ivt-u+lkE^U z;4l-z+zLSSIGp9;2paG-r|6C+05YEYMb*6+HrcG*JKGYoyj1mvfj8I*gXE-g58O`I zO)NIL|3TO8Pv@bZ&gLFdRxIZV>EN2wKcNT2cK0IA6qzW(QBt^1!NoBtbbLv#b5qYb zu&Mn#&=R#k`rKO2gt+-#x zyfmt`MwHsxe06u-CjLkh%11uFk0HP6UQW6~e+BdYja2$>`DZ6v(`w8Y?IsVouvt8+ zgi7hCSVy>ei4WJpox;6IlF90GRpxh&w-fMn{onF&z!!Xgk5$hk$Pb5@K=|i_(;hpE z$|2E%vM>{JHZ8V~;?-!_NGq}wC&RKbQrR1o&=Sfp*Yw=wzA|O`oCRC3e}FRxvfo+Y`7dkwQOO4^JPAM!r?tmmrnCcgjV1> zBQGY`<_Glw)*Zuyn4S!ug`N z;;td$N|hp>Ye=Ai${8!hrk^_C= z2&YI032|x+-p@;UE?!!$k1u=Ss>@5+)<(HF*-y|m=wHmFoMs7d2z`?M!V{9mk2dE8 zBHa&(m9c@ZAPkbk?eCQ|`W%^vkO59EvLPVmYZV8hgr)OvV9M}MzSr-%_5x&~%3HJJ z-N(UH^aAjnzN7bHi+xcRc$3v@`}*KVxnls0)p)_s*@V2`hD()=PVG`jO+F}5M(dMB zV5?7@O!ARDi?xO@kMIi0E}?d!AHF_M)v|q8VsIjak&Y3RftTl)_xZJ8D>O^tks&w)zrkIPeLgy72CPpgPDPhHYZUr) zG<*yDEr+k9q4*|qe%?Xd0WHl|+5ziFXV;ys7e^n|zF_dxc^Wgf)eu1Wsh7`4+8I)V@I=OzhnVOO zgSm~5ZkVA@d_bi07o`~r#D!N-)A&E-HnjGTJ)Bu&taDlTSRpQ=(JCEZ`5%OHTi=+! zsAaxD6Z*foUU&Pxm8bOQTL1fI!?an9pS`mh{`;aQaf65jjEonod=wMckwcQ(_p?cI za4BFY-yPK*emESgoKFibnK3gy@U?1mO~}t5Mzq8rM=PUG;2)>x4;Ei_3L?)_XnXLO zp5OSreS1?8U51|d#`IS_GWSC@bfuJLV&H8c_ZEm$xMr)Z%+k;-or}2RS?hAsZ&Tz-A_wn)J?*hjL5tL?ngBhUp8I(c(GfLuMg+5PXczD&C!QG> z(>%=QUFo*<3DMKmr+@mueA3PVcl6)6r@kSk&;{n8T^qej{jBo8c%*H|-Et#yEfK`y z*5I7*E-h5b1N)%XcTyqPE~IX;WM@dX6k2jl_Y6Mo&mNa`(C)O{44^6H0o(~V?f>)X zErES!j9Vv663MNe$iA8i6wyOQ=5zcURm&adT_URb9`&5f8w9oxhuf0f8x<(*U14dH z<~mzt6%xrI+LKvwXYt)@anhfR`jhI=M^4 z;3GyM+{o4zCj16@=%6211^ncM<{5KTvD&Ix>@hRH5x#vpKjA$^(sq`}{{yo$Ecqa` z3o?BC?RB0!n(wkzzM7=|mtTgXVjE6a*?E5dy~~?^j4gIXzGAcU^n5f;HeSa)ewD*$ zg_r1Gbt5K-wLf_iK<-oJAh(&}`OPl~H&q3Km!CVJb*pMd>`SElxS!PPfkIj#0?TV^ zX0x$F;hoxY#|2PS{STw@njWJ9nv~&eLwZzGW+0c#U4w}Gh7sV{`gWTmzxz&pg1Sev zo((!>VQ2n{FUSre2J-TOJ?2OLs5iq_w!Yo(6aU+uhx-$d*QX#oMQ-Xb`ULfcC)dv> z(aK?-fs-;^N^7|Ut0dVdvYQPaqLY^Fh;_>c*VY>U)>7-#@W)lauCHWuNbYqNDVCbO zACTUryO@h$=nz~jqouqpA!*8-iod6drjSjlGNmiu)Ndoz;?eH@nj^$`4(-cg%>qWQ ze`3BU6GVaVf9X01wvGvmrTa@ImHP0&uP%4=k%`|!G;_~TSF)Ogq-SNiE(gIvmGpgP zu7F0COwWRM5p`5Tf-}3{BI6J&sUR=sbS~c+XlmWIwK|ujh+Q9K;@g>8{gNVBYG}i# z0PSzhu5wn031)K!=ZW zB`99RnDqDQ5xwXNIU06@!b!9nD`8i1qFMOr*soN(caeMK|f{y0Tieiaji46V7v=QPDJ+#FQ9I18tFipe&Hmq?EkP{UG6i* zWsQG~0rdqc!jVPYuQ9z;AvBztOKdd$Y~N?^q6z1Fc0bd`27LNg_ep7tyq*bjUlS;c zrXpv<3b^P5Yo*ONL}5}y=YQB`z3BHA=4lMS`+40VYv6!vnf&_D^5^l?jEC8=FIJb@ zM1Tzr_5)tgJ#0HG{3C(djt4fUCLmt|BIlB)GVzMF(difdi5HVeKg1ExB7r&b3wBQ@)geHPt zQrj-_5PryEt;Tj7=R3tl|1g#KzLb4AR02d($rp8t3Gjf6Aav@;`IRI6Cn-O{q0)v0 zT;cd48k5ydu`co;OQ@8VcH;wU%-7;ymi%IFBl+9(0a9oIusnQ}s^ zMc}F0Bid62B)M%6?2etVchyg1ys|GSuoPFH9b6sYMPbv%-QdOS$`QaJZgvc+?al*6 zZQI9hb2rz+i2u6GK%b-CmxNqzsaZ>zz*12vs|PuYesN=Go_vTN(F{IpOW&aT@T!`G zrEC8fk0P=O8n;GgU{)hjAEh;0@vOZqWgTx3agHpAf{3Gi=XHKIyN^YMJn7DF#5hPB z0b>lVZ0MU>!l(WsuczG#%Dq7+QLsDlHlqr0&BlAgqBWOt4JCFc!Bj0y-1liP188J% zE~;o!zAj`BL3F6x;RM3~0Ta7^eG?duvIVQ{*Pc1@bF-{>-`GBg`kGrezs6I6LFko( zH$|Gsda{-PKQ!!~RKKo9bFF4oI;XuIkCT3MRT5+?Hi6Q7~^L z*>v*yJI46m!8^@&S^2cKLIO5x|4oB9kVDEA<5+Bo!5kUVp9nzjIJxKF8@tR$(7xl7L2(vV{g6X-lj2?Ew4jU7}ny;f1nVLVKJAMg)d=9NJDT=cs{|l z#WO<(TxlvrKDekT?H&=w7hEon7>)T*p>6?V(WO?Z(5j)6Jb+S-dW1)Lus`5udb|A)#U!*ZEMR$%$s^mo$hWiE0r7^YkC4(dA&n`MmFua z;2KHu)tIRlfaHVnJ29ikSktsy%=|n`2qj8-9gQ26WKkm~q*|?`1Sk6S;(SJ(@n1(B zD?Z@&+bGH2pHCemsf%=B_5>APC+*vUpIy;R+XAVRMJmH!-XoDHD6>D*82jf$FwYsg zRE)VVNI4kaOXK&VEEka1M2<$3j1P0J^%q`l|4yzKt56 zT8Vr0SFFAf0|gQh4kr9fvhfbOQlv0}IbnKv`(YRfb=Ei`^f{QGhLei;I0GMHu|*)& zjEP7&-$SZ?)V;)yCP^u05nu5Ez`ajPBc=XM%fqsl+9%;o>1lGT_OMu`)*^+b7at+g zz3wYTzYOv>oIZQ=egqJPMX}~gp)FEehKEN;w|-RY>hdb$g$M(_2m~>D zFH@rqx&vi46GBwb0*F11zP27z`tA$dL`SY&EZY^+o=|eQpUQMy(7x#$!}Qw7LZwMC zeMq4;un34lMGbkB-aXc~2+=f zcl#59<7`StuXSOsd@R@_{e zJywkR0>V3L-s9)b%0lU*FyU;VwpKmURpX=`A_B=Ol1iqu_t+ytmpMq$Hbv9j@k>FN z5K)*E8rSzDcSq*p6IukYAe6FKQOH;M4D)fJ;!HF`tb-w1?6`TA(<_Hee0X)?+c)Yg z30zaHv>UE^d#O`IoQ~imd?DQBR!}%HBjb4A04`^3Tj&NqL(5kwdGHV!Z}1#Nm!^qn zWSp0V0~CveW*k&>slyv|b*pfy>PIVfk}9z>=hn_{fTkDU5)h>NdGxohws{K@eq@Zr zr{qb?JAvQu1Ebb-;c{by0`CcTAzM6;b#9~Z9mx>L7W%~aqr9{AOdyj*so-{kgZeEz zEr)=lrALj98#&TkY$!W%P?~C|W;*@y8Vfu2-Jblj=KhKofJ2-d4=p*l0Z~id`tHibn{k%3>WYOzko7AJ%W`EmxVf zzl67e#(tr}ea!i_9)5>*7e0%{W}*dQFf59LPDCe}EI6X#Xd*5PwVT~pr7bkc(qI#~4;s(EyjUJ!qO z#i|(aTmjsy%+ed75v3fq5$CzYEwR(dSu~$U9bw{QG@lM2A=tSR;@QEfN{Y|#>F#XQ zVPQ+sel#Ic0(HEfFQ{yC>&x7b6U0&PCp{5-V|V@-<0_F>0=Y(Ms;HLp!owHbU;G)s zTfX(L;@|Hay8aO7r8<2AD;BQ@5h$`R6QQD=-YqE@gNL1t`zpCMy_PU*<>Np4fIktc z8jf*>eEsp4$8GfDeA1WOt5RsdzEExObdLJAXZUCh> zTqE%FaQo(~2zXhH#Xn_1I;B^t+NuF90!Y)ai_i)$EPMW>rBraUKz<(8#Jm+6g_V$vULN?$AyBXsW;g!4TZUC82` zL`sP)Xi`TV;flm0i{O~LCZqkho4xH{>cUYHA{Yp8Ge8F18~Rsi*0CP0ntHA-2R19j zavZYX(FMZcOQsu^iQz)@SYt1oLT!(D zd;8Zzr7C6e_L36fq@p`O{t!_((0N@?>#ETVKNAv3mryNjm(#A!E0}{_H33bukm(># z@OGgkf8CS_pLt0^2!{&AmPOb-wUk;J+J-uNr}8}dnTz|VTFxg|Rln>HHD$IzMwsQ2 zDf!z#7`IaTbke#oz`>}R0Hw$nV#Et995MR5-?wHWQMi0Y`7BD!26(m7MlWefg@}Dl z^4O}>{SC*{4m`$yYTv!lo!I5YT?P^CP)MteA}{xjp9Yn9pYA#wC;3qN%KXGc!<>O@ zN=cy*NE{aVE3tfHEp{V8nVWZSe0VK`-vD8*9mbFyDJ}FOkwhFSjD&E9RrT*zi-1vh z+T1uK)qX)IrhLiIW%Tn5gTQ@JgUyA=kF1Q#znxa$7AA|s*DJpbxsO4Hq zSZvcxbD>8B4Im_mzF?5@E0QxT3b(Cv(-(a041!It`D(5FY4v)Y#JMZ6YezT!HbTfHj%dqS{hKdg zadreLNSl%-zAu+!Ryo{+3_Bh1q4De29HtqPJ&mTINt1YC1oXZTZ6R2=_=M58+;2TM zEPwayKA5yX;e1uh@tBf)ENyahbYWfxF~rZ0HDCb4ekjeqWHL(56{!{1F+Z)KQAn_! z1TJ@0lD;we6?uf-y%cuz@c1cg=!b}sVIaYY=kZJBl*37iGe58v-dQ1& z`roIw;-O;%NLw*NdbWqh@hzRr<`Xaf4j%;%?L8nk;-;?N-ZA@d?&Guff9dS9L_v{2 zf+Outy+NtMF7@{`=J%S#nz55GN1z3_f)AdJ#0I*PQvp#vAn`$d8rqHR*_bCHo6q>@ z6m~0#kxwM{xXw_aJP8|j7L6qPJ>Wdil-2u7bZ6JUO<^Pn?K2d`rwt+b<_`T_KmTKe z%T_XuCN?;mW-eFvfZ}_pkCkvzqKwcZ@{+T1WqbD0a;xhxSSAe<{oRN=lPuK6s0af} z+bT?VmL`TuC`j}1Yw1UcIc;xi7KhqL(y}%PxI7KrB4k&WN3AWS&hDf$lrU8(?|e-5 zfpk72C>yu_LGsYk5VcUX^mT!InQD^*U;aFo{q^a&p|6IQyY(0SQP&7q={AbB_{3n@ zmCehC#=D)gLg_RW4P^2Hy^YXrHOpYL^$&mX5Xe7L&2n_%TyLB^6y7@L&ml>cOS1DP_u@CWq)$HZZU? z0#lTt!~5(kEb`+8rY=Y);@Z38|JSgxjZCqjuik`Qnq(y0J07^9d?cfgpu+w47V|!S z+P}5)MEYv%#Ad>qf~*VYdB&EHod|r!K4h4NGl^#haXJl|p=<>yrIE`d!63qi0I&Tf z>;^n3EegH~UPX)5qtg^e;nO%2PyDe1Kws~#Cza$X;I<@-%{#)}ch*%&qWKmTTg>=K zzj1+a6U)1npn7QuCS7{FBArQ})8pTK zHC!?ZiJp{f3_@>b-ya{^@-6@LC0*3P#O5}Yk6jdYP*0mUeq^Fl{WZ+m6qd&lOZA25 z_>13tBmZ9uu;Mupr%VJ#Zt<(c^X?QUw39hG)NbR2lGTTb%(IAMc0&8x?OcwTL2`db z)K_M_Y?Sl%2{I$Vw*@NXsPjTA&^gN~cm`BV^tIuQF!9X|Imjet3e6j7D3|4SU`Gr& z%8EHB$cZ`F!y;$Yn{<`t`)znxnPJ|C;J6VGSyIqgv)t9Rbi1Bnj>p6qUwA@Bi3JH8 z6bX@qug5*eBdS^V{a_|p_2f_;tMz(&2Hy*hcj!l(&I%%rn<&J$pzmZ2rI(_SMop6C zA9_GvFqUk*RF48}4!V*ec$|fs!kznh6>Q}=qD5(u*}kDSe6{gB^Tb@sFTMAhflDL68zjl7xjqUB#RuSJdKlJ( z{u6d6dqwj@WNF$!9WXu&`#iN`k!iMabBAy4s-b|#zt$wf_Ly+35&$JHxJeUpj7 z-JP!I=ZAdnaDI!N=kIBeOkHv8?i>&jB=B0(R^j9%NO|-zM}RG?AEMy6$A!3whnNp(Uhn8?R(mI zIA4=To(@OzLxtr4UFGWDm%o(J5^(e?`eL|+)xW|_`=nEk_H|}m?U4jKO<+r959pID zE2kz9p58OCu?kfD=2Uoita@HuSr|d}sOrim1W!^-Of~1IDTOx)@*-21yD8QkUXyM{ z)f2+YfKOld4a^ThxmYPF`JqO%Tu6CFMBT?H4;inuG|1r%cVu^2S`0`iVcWf@D?WZw3cfS1C;ti;cwfn-3=bvYRX9K8X~#7!xXZkVs{gdV`2a+tqO); zmhe#HKJ;6RBdnQ;4s5LEnTQD5b^As|xM)VU+WRQzv=LMV8TgU)u^|Z4ikK5*LIo8# zd3T9R^r(JKUD;S4#{NpnF%g2ZFn?nSni*3+Mr_ygl5nBJ{hbTz4*P8 z8{^EG#JeSQ9v-$}f|J5*t`m4c|F7RnPO>iP@AK~h_^J(h;7K<~FMA|7jBN4eLk%}D2lY)TI)aC$Bjm#VrBW(*6-)L*e-uLu1dtkn z7d4`Ps?LlbI-+fGaaS`O>N`BND!|YPVpCGtfYSq zC|5L&`Rrn6%e&B0JD0*`%e`Q6An*Z><9m0Foscr1`)1>!zI@;*Jy~?`ocB>QF8h0ORa43mM&iJ588iyb*`1 z$G6L zKjLa|a`E~(Tq9VF3tMdI6FLE%Yhfq8i`#Y_!{uA2_xK4!H@4hykl+<@G` z4BdD&Z{x=3A@F{?c{wbSd70O~sIQ@a6_j;Z(_zs*-R_ot)OB@BWY>C6T(J-qg=iBv zaUdWD>#jg1j?m)to#Mw7K%8eZ!RUMZGwtMMs?+ESZ>vlN4vY?RP*RPF1Gx)j{Hnk& z^A5|EcgEmYf=y$Zmz@i2Uu{y+s=WS#?W7K4u6o~$@2OD(G%pK}L?!o^*=AqupK z;6{hVQH8_$gD4iUf>sEex?tCQB_z+iXK1Qzr`+qZU787gHt^^&SLZQ7 zVaE2k)_yz70tQ{=3D#@ZJUlU@#?IV9(~^oC-%JfY@tHA-O;76*D;Vg!%CX2Jd4YT7Gva43F|(S-@plmc1#ESvFE)n?w!#f#*Hb72p&s_g7og6a3fg~(3fbAJZHa^AndQ(l%k3df;$2H1C zm}DxcUVtR{N?DcUCHK#!9UG66IXH2PB=&E>x~i$%L7hN2&RtA#vOBRf469FU0x%&% z1T}Vu0~lUnkA5Jg`|kA^l9_Wruehf|?T)P)FG)gAWtAN2qk#KrS}Jl7pq})xZShNs z%|=QU#n{Fu0FbmY+O1a9g5uSexk#fLP2Mw%t@!83$u>>9h)$;^gMpn4yZPwdrv_qM z+bW;jDUQ;~uEwWl*p%rJT1q#er^jT%cmtmb1qh>q1X;9K#hgZ%%>ZpXP$ zo#>9_2!GYT!Xa$EtPt@pJHWA|%|j7ES4|(pLx?uK6}FO_xs1whsDa++BF|j;!@hJl zE{?=6L=8R`3l;Sby=lClpL1Mg;w}uN2ni&VpKKbAg)>*lc0G=`AWys)dSxfmlavz%mXedfcmnT?b#C*5YjfYHZq9bG3um(Z9P!`zt}U9Pl+%d#5J z4A1L&BBEb2g8)mg=g&lcPI8KQ$ypQ+cmLr_1y;G(6nl#lXrL>1Q&(}^M%YoDhF9*g z{7eA%FMe4-qUS;r^E#OaH2`bT+zs6hN5k=d@|p>@7kB|3JM5zv(bEz*@%Q>^2xj#n z2P2`2>jQ}KZFiMtejq1qx-aTxm${Ub1oy5>fh3sT19&ggDG`N9b~`I}4w1jA$snLB zJ7N&SZq>~*8s^l|jBWOQnA4l97E_8MzBwee7`^9G0GEi4OI$xQV5}tlU8h%0Zf&i` zMy;ZUDvU#vwDgrdrr4$>6m$8o<58M@6CQC(UrcZ4bdz{4a7nVjW)oj<8cvdhx&INJ zsq@3<5Vq$Kf@wpcGjqw;bfpekD&ItVt~X++rfKpyQJ~C^2AuS;#7__7OmYg6q#bQ+ z?mxlt5b)MXkO2^}RDaL!qt-r2SMHHLG6UE#pl(%9Phd0GQLu?adaGAi6e7RG67O=U zie*)ZSOt{4oKo3zuzLsrfn-iXz1G8Wat8Np*1+<}G1A1SmtDntZZ7*_AM0XH z=859>_N3n_ZHzhszs#;($bP&5b9_bNNBPd8mD%}~$*3g%Nx*rnai5EO1GY-!_hDs4t7 z+azwHbrzO#J->5~;5ZTz06R9+#mPD|_$m#coo>8gw}3uwvESS_P9(@^ru=Ac>d_tl>l_yDtT|bWfG3qp0@~d}jXAt8D5*)V{^CN41=9CIL9n0Tgg2Zp&FB*C9WX85Y2gIfkNGC;=yp3DY$Jc#$} zv!FNKlw4M7&mqVl$LLh%=dRQfcjsj$5UceR&ZZ)tyJL3%f^lVN9DXn8olS z*YkIAxyFZ;ON%G~Hj)h-a5YJybUq${mJI&Mf;_;!vy=gGr?U>p2nD4m$o21;hfTMn zJRfGE_WMLQ>rz-f>}wkr^!I;@Jx2HTLE)S1KAg8Y(E{B@nYb`m6`Jk@hF7IBuiz|u ztqOymqW+Sem@x5W;Uj+B+YL}Zu6 z*S{T(>dez6UYU1OCE^}a64Db3eY#NTP5meB#m{5~q)+m7=Z-t(g*jNui>(~0onY^$ zaqG&T%)eGcGsa0yCY>=#8{2ww%zGAk*KSCr@DM<+BYZHft1~jyg0sc{GXO-H^+Yj) z_{JTUF%F50`ANm=wvYWT#$%yzy4W6!Mm%Yu1g!p*G7bDTe%iIWRy9REXMQ-|d;J0* z!|;!{we$4nTd!=gUR-P-Fe+}H58-!<#MzgYf15i9(TP>Uy@SG|RF^-mQtZT{xm?Ev zuVQ}lF^&9lNw#uvu5BaV2lRa}{Q7tm2o)A-l_A<0LgRMLe7Z?u6$rK?@s#^^u3;$4 zA{m1ef{D|iRjtiNzwCX5ua%lkj%^tQa-0cfFi2wi*Z2dqQx^CeE>*yl;}+A6@3JtF zF2(!O9ItSGeIp8azUnT9)S*!Tf^m=&3^rY}Pu|7LFUY47N{~8A9#YHja1KO_Esm7j zYo3QB3L^L(Eixo227Z;8^Zu$)hp%m*g$du^AIncd_M{m|Xw!ED`|7@|^F8^A{0$UqZ4VvS3y7chu1l z(hie%F{E{itwu(xq~sn{0JmLD_~Mv$|C6qqFitQ5R%t-C49nf5l_JLM5G*>pu7KR7IxU3;Fu^v-k&!94; z&o;&281UHh+Fk88EjRE#@)t}H4*IBTuHQjSz$i0(I0PB5BtTH4Ma*h~YbV_Y`_$r1 zo&ggLdGh(7;R`tob9g-jtO>p&p)U1Otqh7vWAGRwDpaO+GXpT14%UkRf0}ob#sRYZ zFAQ@N1p-vCa0p3V1G$e{U&Au%1vBkuDBin09!MiN8kj#ib8?{ijd|VXQZSR zM}5_7xHR9|@h=DB+_YKp6wVC<+5FSwYwYFSiH6xt>ylHo-dYKC@%^~@1zgT@x&?OE zdCS~{9CNFM*loJ)5+VgwK;H?Mj278U$xh)?P@R*`0=)rpWwdrkwXdt zElFS;aWRDbL1h?me+RqSj3O~_{=yGXaUuWM_Zp#M(nhqTfeDqiEx#;RFj=yB&6`Y< z<;0g!ZYz%TE~P^HEtG_GM6Z3)3~%76O6O)U=Zr7Vv-o;hdwd6+n62F3#Pb6% z7lhN^J%#2Lu}3HA&G{qywk6nXBUHko%<)FA1Vi$nbTx%@`!whB-$7ytzEl*u$@qf< zxttKHVy_t9?O{c#DYJ+Kw>OCoO0n3lf|qaX@o>k7aadCA`^6#4u!x|z5tB^X=1-<`5U8oQWA0FdAHRC6sG4Ls|kfzs|I<$Zar2W zDAM>8r+9fzgWNCz_gEL9&+V{iT2Pi+JAc=qew2_g_(LDR3cJsnwps{U;lwNtqKTeg z-oazQ_@IqT$d;hhR$OY3N71K1eLPyFfbts5x5f&7HWa}odNpkc7A6$Y*^`mKG~&Cd zAd_5-PX8O+$fwY5Ar#DPb`M-U=e1igUFO%_RI^c7H>qBCwrp-1?eig^E`_8vS)|Lh zIw2-YD~$};bUZ}JiFH1{ss-~yAbH{&y6KxJvI8cOHJrOBT!IJK@Iao(C|qbvUvUlq z(u~X}xpSE$n;Nvo&3aC)@sj3$;vkFqzf_!*>0#@Fq*)K}{9lj%sFfqPH4a^DR2Rl9 zdL8>Q5psU-m8L&_p|MSO^Q9Z1AVb5qWrY`}pcEq^3JTh5!*A~gA4;|c*+RLbRA^>a zt$!Ah*Noc721oU0k%GNREl*8I!)5lLjT)+XWccFW8~%35aN?<%#6u>AxL%J@Gc;f^ zwAvy;1`Zfi#M+a)>~RSedb}JHs(mBZTEGf|-55YWdzUy?8tu{6Ca(+YE*?XVWHD%C z_TAe^F{I2#gbMDpC9Bi^VS!Wfg^Tw5Rdhlo$*!Ld3Ge61?R6fDfBj2Ju?%_!3C0sy z9FKvCK{=eik!P_p_%!6fK&dFn<}jy5Oi6tT8F)(ZsZ+MZpdpsK|GF4wJVK2OWRwCe z=FX5PMn^+<|Mjk&_RC}tlKNrsz2@?dWsLO>6D?h6Q!;$qUb85fS_pgII<*{V51lRD znHl6L!@X=KEM012ZSx!>XkCSY5`K?ota)bg@yBnG z$vif39gqx@Tq+!>#P3BU5<3AAp_ZYAtlg`d9ziLec~j&=v;I^7X)+dxjx!jxMd2~1G%iKczZf|?-Xanbv%BmOY z8HW^^jm?P)eqnnRg( zZT(XUHWl#_7NpssiV)|jeEER$2u8>t?Z1Ixk>;=d)@e*{EgrvO4xm0L5DpmZ*40O> zR4hC}AHyK!!JiRDbGLbk)30JgXJ8%#0y8T1Gx-paCc)sBK|P^Qa3kk)-hIWHV1E&T zpy!rxK?u^PeD~}65p~_LlB}po22%i#hOAOxIOdw1J_txHucI2TI_y5=k~Ci&P7Yrq zO3|-B0Qe7uT0@}?q=E!xIu|0H_7Tz%blm?y&p}qXWTf^c51sh#ZBbW?-5`M-dV&%Ad71N0P=$%2Ah@ru2a~VmBR~I+Y{u9r;ux>C+C9}KL%J0iOvY)E7-BhJQ|Rkc@Rgdo>;9Arx2C;!AK`e;byISSe_P)^D$z`Id!L5V!%+ ztBjbS`jIT0S~%e{+T@Djwz-AgN89*a*w^cjE`9*A9@|!}8X#~%>9dk8Wgce;jsY!&z~3ehp%8WcYHbV(k;sWc`pe>#{;f zr|&2R>h=DcA!tIDl+QRlboCJ)!FTmE0{>*U`Q*4S_Gv8kg|pcPYK;G@d1ldBZlnxN zN)>M6RB*8$1Cc{UBk8e`)b6tpVg^`lXz%!=`H7&tWDqMkTjbTb<%2kUL8+tXM5V}X zYF2A*)RNHeFU3nrpup4xX+YhYjy%QB6`Fc!U-W3d*M4|Z5xAhRJdCp(KO>4OBq%rV zQW4~hRJCEIn2VFYUBnlWk4q$<3$QfezUsRndM>xmq zq`#C23r7ypLRgn3aD~3Ldi*7q#D~fGf)(N$p|46wDNl%sd>Bdi)uDkpgU!$|w*8lefqzpZ`LU!xBcdSP#<9K~ZT0Cu zN_;4vp{y<{sHI|$fqqPQIx$>w=mh6$9A>+KpKE^m;FF@euNHvVxRAg#r)y1H%=-D7 zg7<=a+bGFn_3k1<{M0?1_3 z((Q$ji~j1>F58x6Y5w6uMkW+Y&y5PlIDzuDBJt!K`oI^lv+zX;lFw!dUpOLB0>Xe% zC|eTq4xk^Wgta85zlIfZL|cebz^v8MFpcRPuMOWLHC=hs7u{Tk7p<&i2}tn>7ymrl zvV4&E&92MRV5{b1X&F0%Lo7PkR%zG35&}^bIz5Zz%Y1(HqQXX}6dnmc9zV$TFqI?q zb0D8Rs%8|4T3ujzDiAXCSM0s9Q57NlQ-jlrXlJ>O?=H=6?|(uzuX?)ucoaTyKxIjL zYHe{&{?A_+;;Q9r)c+DN!Z}y;R?5aFL4SR_CZ3#KOI^c&$-)kbH51BeDcFhWCV|&6 z(sya8FtOp283V2y&XJDECa%W?23EP^7vfkig!j$fkTk~_~Hv|#andbBQeBFUU3y^NvPRl|A={|qpB2W67rU;I#x1EQpV>gUX`!ozL9 zs#eoy&i}~D=VUWUE|)egs%x4Yb`e{4?M|Pgy6z1yBmIFtw;Y1 zGlC9l1&wcpX&LvrV21=dD$0lJz-J*vZYyG*x+ThTb>AcZowm|XBa@wTbdj@-Q;Z@9 zq(BX>PJWlLOo#?x4BBG#!Ln(v@iM=m=Cu|q=C_;n%G!UVDrG;5t-TT-Cze1!m~Ax) zzw9n*MGc+xgy-VJPQ-7z zgvTmH|69#{I=iTKNwt;o%PYajWuNMGi*aBz681VCb)N}-=8CUv{JN2!eG!U#u713W zn4h&nj*eOwCQ+;R)^)(B6*)0F2O|gCbcSUp#T6-oB8{-{Ie#AeH`g~$p^f{g1WINt z*^hc~RZ`f(pjnd7F%W8pQrsA2W@I=nNWC=V53AVkhzEm(AP-PzB#4350}Xb7E3cO8 z_3??LTp?OIFtEh%4+;OQNURfSRT_=_v%2H(A3Swbl^S^31dFbwqr;wTx&&XQkGC&I zSc}TfCR_u*Kmyo5k4B2YN<8*Ay$L5g_;}P#XIf4te!rF(%;GKKyk{-`EYtJy!J?)l zb+wXL#*BvVT;lv*iO_O8r&%&k&}pNp-H6k0&iKCDntLOixEn}<#F{3{5>%{@Xo1iW zN0uqV^%TbcS^p}a_4I;JL8oRP=fg;;Ub>uHX2nuWEHNGNu^T!kv^w0{aC-)Zb>nXh zz`iW8#HOqOx&{p{o=u_~cfTj^?vpJhdA8p_@N3tKwd7Wl;0m(#zV7 z^uR;fHm*)`v@UE&fHEBVJ4y$N#mN@`JssWsP*j;j_+CGFEpcE5Ug=>KhBk|(b-r8iouZn$dT z+b6_r2d_aJtcYdwg_;%}s-`bp?nQtxX~XZq&3e_RMp3=sKVa8E3Yr#rMCEh4Cgis2 zONXWiDh9W^R_Y~4Fp3Zl@sCGEi?u2PMPKevV9F4Y5;Gb{asA_i?S!84Hk}(ITdBqP zRW4VWd6*!PR1jL&IMQv~W2H-rJAjVWp`ZiqoQ<1q5BXe`n*V%8w1ByY^HB8xiNH3@ z1W1#CF=7zVxEKf)9b<)mdOeuSK0Ll?p0Gnm;+E>@IDHBab_Yt?avCA@9Z@AGlg}hg zu4i zi6NPiQoJ{m>HDw_Rd6`Nj+v*j17v2#4UOy`e@wNYQLkCp_$cm)1O3I{>9e~T0eH$P zjfQ0?aJDEDSCN{LSfT_*-GV&%q^*t>eXyc7`N5Y=f=F1#0jAXpyf!(kMrWR+7%3is z5x1qPi~6};6tsnTfY<=W(^Z%se6&!H-y|J2(&VyjR~CXKT5IXl!*Htz_mi;&j&7wK zlNuNeCNyXo$mw?RcZ_epLw!3;s{FQk8skC~`r6$$F#WHt=OsBG#|^#gIHo=Uzf`46 zx<;T>H|&_S?vqF%aM0oYQzjLx5kBls6lsuM0cfH&NNokO!BDNRBZ#bMy6ixUxH|pk z+aJvlxl2Q!r8f*}_whJ+WS6~qK{5Mf`grkoR1tIannbo zHoxQ`XdD#dS$L=8->Elj0NXDFFGv5ek5w27Bl$HFmw= z6*iT*1;AkG>E7iwHVbq$;DS=(qMadwO{OOyP<6z<(PhN%%ZArwchVpH<9`gKBN0p) ztx+_>fy5iA{jnRfgU!r{qHJ+04Gd^L`nI9aiIMfI*FY%nAp^r4a*p>wU8|wwqX1%y zCtYyD%|Zjy_dbfxb?_Ms>gQSG^Vgdl=L~bG^t=N=tH|PR8{<4p+oxe0!d|>nw)V^6 z5|Q^;;w4=NY&KTf-hY`}EH`G8gnjQZ61xk>^#o)~vQCLM{aG>=^`XH-7ngiW`MiyK zq#qeC48lA^l{AHDA#&3;O2SwHwERb;u(U8SzE&nkRazgoO<7Y+B?W5J(;tN)%hrj& zE6kp(x933SVa=?t!Gf9-M;~PdjhHf|)UwzY#Ljse=^CtOJwg^_yq5xbzh(-c)yR@jjFl0%{EmIRFMZKE+X4ut|4kNut#faKij`{>==-BR_^r+b1jm$nW4b_qWt6B_T3dUHo zk;%30vk3hqztFn-Q-Fy+McLOV;AYQ6eDiivVwCeGJUGJO5{Rd@;UFEu01V<6pWp;F z!mr*&7cvhJKMFxcn1VE+IbE9d3VvKzQ2r>S76qjg2^-c09-g<)O>%Ll_Xk1Lomi{V z4Q>{?Eg;z%C@P7kBG!9FMM?Op%@qS!l5olTIa2ECIjG(J%yCr|e>eu&1sKguFuoP) zxIX`0e?i+iE$QuQ@K0+8UQS@OaieWhbB?{Z$50R98Aguc*7APhL@^H&wF%^JJGDA1 z-|aG~{aW)|3!3G>Ua$pll+eSBW9`dBw*`_Z6)+RLD=#Dp?#kq3$i4$izz4STQJIqu zv&p4r7JUM&HT9%T%nkV69UH#tJibe^XCxQ$U#zEh--Xv(9=uG9KNwqYZ^MCa#&$=M z+r^@L5!m{W^ar@TEqML!4^e>ezG){eGfJ{F-i*5UvS_^F(Z&&72GJIm_vrXf5_EN^ zw^L@GWOr4&`#OfU|=WiPnM^;A@vUJCc1i*f0?t- z;=`f4A7p4M_)*F7?R@}tHP2-^{0Ay%B;A8l??L|NEA?z>iN!dzHmr@fIr3`UY>6_; z98F$3jmN^k(#zv7TD@^0VyIp{apC(KB8@PU%Qz?)!96cZD$GAF{i3Wb#n~|)g5!^a z{WFof6ZC|HB{HPZjn!*)vnDZ~`Tc#m2`DY^*Qx?9GkuNg4e3==Q#D;Ef~+trddo9mvCxVU3)oJrs;AYO|EochQ*wK7n_v4uVF|Ok6-#}UiKnO zlC=8WYmFUV2WoN_#s}(aSo2>#-oSdS7CG1Nbwk}t%Vo%T1;KG@oi2luNO z#4u%NXXD8~?Kjy8isS**4yXr3bd663dI{-N%qp_w@K9{?%h30DOYLQPmvOu016{rY zV^qimWG!Gh34KFiHpU6fQmW~G-E_#>=c`+`($Dw%jqj{x=Iz@OFz1w4Z4?_meJ<(E z05~#1(n}5oCs5S#F70l4HNP&|N_0YPu|D@(P0iC4pAw_@G_x*PJMJd}QY25z_V{zZ z@7g~XDZ`kT@sxoG6BEQ32`Rw-Mhgbm6XX44Dk7=_EF`ssl_tEYGj+RxE`@d}d#EXm zXWwEh=QXrW3(K@9DwUm;!XcKFuO)h2reK(}v!t^KAYn|S1+f3piBqE8vG{8WQ;^ZD z%?RKq=6w~!`VY1ilqL2A6`|GPWP@=|#tJ@b5-zA_Q$WX8qhXH1qZ^o*`O{!@xqNd+ zb`fMl9nU|37cdd}$DgvLVNaq3%u|Baap@Hc&`sE8CF`;z;v3!PVsCcjfXcZeZ=9{y z4pS^uPgv0{A^af+xg$XmI()PbL3P{S5ehXeYN<>Fj|$EE`Ux$Zbk2{#!Z9SEBlHHs zq*W}21MWWrgb|hpW0?uH6qF)?(8a6{LnaJ;$uYL#y&R+$#ves2r)rv03r)KBRx8~Vmj-bgkab~@%B|bICvv*Ru-jflfa8Wm6icY^j^wvJhqA4JX2|2fs!y=@U;fELw<8D=08Wie)(=J`kkCPT zwJ1q6!c2j<(n3`5CJ5VE_5MU*E>`rs|A7?dv%>aULyvf}(e&qS^EuFeerxp;arley zeN+0wtPXO=(H`cL<%FTWPmUeItibf&=nO{{7sacm(qQTjh=;PrOodI{*KPdG+;Wyo zr!ERwlpeVNe?t+=0NzYws!ih5_wuml4m01^K+8Zoz1(=LO9^IzQ#xDy_jTJI&o?jy zOPZ&vK^YR|*p08gE6P?GGgkMnFCj$U_kp|tJC{J@NgbG>0i(HkDmbXQ)hoFS&ilZ> z(Z7KtlS4+^x3upe0HRKcuTjaJL|`$9Hrj%X`jO?L&<{z8W?NQYGB)h$&ow(Mo+~W% zQyFl$EHd!X!tP_0Kht$?!fn1U*l>J38=KHhbx%)(Mxn>D9f7MwiaEr};15S_iVh#M za1JH+fj8*fIR%BVn|WM{I0L=vw;4;>sAS6as-!v&1J3)``{jtr-3IOn=?~SskL^q) zq@;M${%n*9>a9M6xebj7Il4WCRWjAM`KjiCTd(KvP=w=B&h14>MldD@=PZHwb&BF7 zbauVfDs!=9+v0TzAx?Vd)sR2YOQZH5Y6V8O+}CiLHc6>&zXbkdTjSy9kxkEaSM{u1 zylALbMEnjermSOyeK=o{ZBFE5!y!g!K()exFSi4|3{MN+s>H|i(LP`v{3%C8V~={W zgrq1#rnG6Uc!=9M_}pqKI<{(fn-FEM29~Cf2>q6SRQ(;a14^})xIK@Y|AAFb*HviA zD3m;2-S00R5Vs*13v(o2$$?Pz*eOO~u7_XQazy6RO2iKg*d5`2kXnz*6^m{evx0{M3a*iclS{IW*ew_Q;U*ocOIW07P&tTNN*T0kA$CoBH z`aP-CV4#*l9{5Bl>+$ocM@*Z#k-rnxN_?mf!Kj{qZT&>R2}n z(s~%t`hkXLEgCnQU@}U2ptAL1q|UR{a%K#ZezCV!?V~Mjfbe5PRh*+l$UV`h1oY+9 zWZw5W93QIq7ZkQE{p=7xG8FW_hpW$mOP}BBq9L!^eV)se{Ce3I5ut2Q0ILR4%Z^15 z4?IB~jZJkiXPZRkro)fMuCT6)EuXz>%&UO%m%;pvYLAVZ(@e{lR9f&q^-s9q)y=Sq zcQ2^SH|HmLv`bYsVx_pumski?cyxEl7Hn!_`x%l?x9-B3r(e|dJvN5C=ij?xv^ ztIw@VL5El2SzGCmUHtYc1tvXTN2*Aj)kS$*ig#HOQD*bZ?Zj=9M#B;7uthw9rwzHE zN&T|0@{2Dt={2vU3GW9&oc#iBp_#X23b*3PzL=VO2yY->`YYtQmJ+8ktwcP}gxxqg zM0S<)rT=@l@$gk9ypQ`Vpx-#{c_x-xZ2**9V&l`+mY3Mr#xnZ++4*h`Ra>Hlg04kn z_^QO+w&0>rR}tU)VfyN`*LBzZbJ&#u1^zKrz~AC0g`mJJkNtU-XXRKFN2~BW)@e>W zikKf+hU6_fe1X+KC*e`JDAG^I#*7m5N~jEn--D|6FQ29z;K7|p(}681OpcjRqG#yP z*+(JYe|y zuxd2@Bb)97Swe)%Jn_)u0?7#tOQ;y}j-yDA`Uk8-r(ox?T&*(F=DQ(tgc#$N+G#$N zj`v%{y6@C|>_+5z;Eae0{`VGWt+wkVxcU=N=@P(JZBq=}-!+x*2TPZQSJS<&5aOke znevA3NzbW3tD*9^yUbT`lz^o{s<{@1a@dg!RA_~j739!c8opeVlMGOtQvGq;lBkcg zM2OG~UX`9dkj>@+Fq}7$YMT!O0mvjmD5%x3aS6VahCsn*O_YMuY8fRq zed^B&gEsh?(GJzm#2qbg`_`h~#$d9UQ7-)PiYzpI3Aki<-(_9+_mEu?CU_IP_uysM z=nK+BeT>zEm+-61bN}YMP3E?;%%t93R+U}-P>E&OId0(D*GUrt!HLeUiwqB!?DZ1L z5ebcRwxIa^6Q>(06wg|2U7l%mi``#O2=Q={G&jS)rU&iJ`jz=FWmji*t$Ccf7wO($ zfvjlniRXY23}-Q#;{y)qsO+bHURH2-XgD7-)(J1eW&rjQOBJ;^waGQQ;it&S zPFarS_+tL@S}po`EuL%SDZhDS?ji}CPRN{27eGji^LyO9CLAQRyWY7X7rMl%93EZMBD zFurK;Vd+uZ21J8$l1>G|CjwZ>mGtVU^xWDfB=E&Gm+u$JHxIcqLL8 zwk7|^)i=M#)kf{c#-y<)P8!>`oyKl#G`4NCvDv6G8Z@?T+xn*OIo}WG`~&-%+1Gy7 zy4SOAa1avmaNR{&6g{0)TC3(KlY%~_CZT-(lowa}zn1$fB1hQHGfVL}b#ixGxS9`S zAh31z6OhzQdCFvW!BMT)ZnU1-PJ2vO6)6@*DUGcmnskF3G`3^M<9Z!fTRVXzkXghx z((VU$^kMH!zV!YEV%tkjw2Yqq)PqjbMHJR@!G~l10Zo89{AH5!2^K$jiI7mEXbC#j zevrL@61I-D_ZO5NW&hqRJ^Miekrr^OE+aUf@l#AuGz%%uXeM%$6e>O1XTy*L>J+o@ z7Vv4xilvKh#{Lmf=>S&=Mm$|2{1^K8xd;K)w&@13xk9wtW9DQ1dQ6YM?wB=i!nWi3 zRsoHRJ5pkH^(QEKsUH9p6riAK6VWfB1fZO5RYd(#Nz>;OBu9RAh;}zXx+QLgueA(K zvj015-sqdlq;6EPsc^n4V2anTt>N?dcEQyPXH^A9cI^+a4MrQ*AErYUySHA2OOqrB zRZDj!W4EP3oY=Dv1d$~1>)PaJi?)Y0xR;twH&9p{S}Bfu(3F(uu3@PyY7>2SP?l>6 zxe^mq0cG3}ZZ??S?k?T@erV^F>FJ8j2`|{M|+qGm!$&;x+~@T5Y8NEd=TXNTte>EiFeIa-}pf z_cjcm)E*6d2tB%L+}6GAS`TAC_fbAxTnZZ!Y)sH~CjrVj=7UkD2mmo+IDw_O9V#;d zwJO{;=mX zCjH{6jitLO)S4l%1}GO1_&{W}HQkGI@4FBAeuIOKuMFQ7342>BoTA}F$Pfm&+Q4Gqh8UUKvL4QHwa0Lzs zL0D;`In7C-76Dtr{SHqJbFe>6W9T}}amh>;B5byY4QS|~*s8Ei77gFHGx14R1(Ii$ zS!@fQ#%m5JiYG z9B7GO<7cw8O+}m!feww_!bDIa)t*d`LJI74KAak6pA?()xx=owYF4a(E{%|t+;#2# zRo089v|cHZFYZ~aqy5^IJh8(I|83QMbb1RpuYdfOnV1@?qyY|Aqb^r=TA?C#%^Sz= znWb~z{8BB-;BlCs>m9e9eO2EF_~($-Ztbs#o8*C)V+{UJ{pFJF)VWN1e-Bu+GXf?V8ZICrmQBAB^DJAfVjO3S)P@z;xv`a)0GHlH!^IFQ_ z?Tr*Tv`+6W@faS&b-I5Iy3#`H5soDBT9pb>X3BlB(oFP6swxsDQXnvoQ4U?o{It_l zJ^PJMWrp{h4XDL#8rh26>i?cmeJ@1Bf{aV8$ycIcTEb$w!l8a>aPyt2@yxFB^ek%- z(dvoV^XX?$(D*kW#q+jpjHLC{Wp@09lzL1xIN35l&4j})8G3DvW-qvRc#r zX`RLs%*ko)JJ}N{MMpMZGZu3-qh>AFU_zbT!`=9olo+Trrn; z&i@GjL=A+V#FpbX>Ye8Da@w$o(n1qa1a7R(dF(~{kmYM-f#duzXAy}!!!ObL46Z&^ zI!1J--~D_45aw0(a;CN7^A`7Z!di<`aeDYHEZFpX&h@A7tRK(6PD!mwx-W@Sl0NqR z$54c5t6)+nR%)mj`mjh{$kSR6Ml&?kN4%3$>hB*1SG-jqCT+n4*@X&!?efI^mv!EU z!iW#`^P%clUZN*Ngbv#N>D4#{(pItxy5qbDK8^q70{lKoSVV1)61a+Wc}Y<$ z>#JCohe}{m2b3W~SdCD9E!VLcSYKmXAd=DmITgWB^3Xb6_D*HeF}WQ&GORxCxCVx6g+~i)s|+vN(cM z2CW28>q*q)2(&F5s`%DWZnglcqz%r6rp3*rtOng+lr-&XLkV>y-PVJbCe2@!5Ea}B zaB_|WS#AP#^jgB-4(orHi)6&mv(-DsqU+}LTM^L5030Ohc_lio`@tY*n2>y&8iS^y zPyowpgmGMZLZ9N071Q*`hGmHh#q`z%XD8>L?=3Z@9;Lpjn6Y2nf*oDeLRtnVgZH;WF4 zhN)eX&e z=I_=-cxRurVSkGsQTi&VWgVi7ITfX0qlMZw@oQwSrF}DJpPIblUBt? zjVddC#3*g$0<}kDe@FDv`Jk@*2o=LfJo=m2i;;!~f=Pjugp)=ZkRAlur?Xy+yL3K8 zmEZO1&=nH84G%!Wpl0Vyzsk%cV$B6AKEll)C-Eo|-3O2tKnG5rP*9x|&0S&LaOmBK-u(7! z(pZ#vF4RnFO}TJ~xxh>f52uLj?`FUtQY!wHz}N2gj5J3s{*Mt04vgm<4;#ZC;yD{1 zsy_8CUH1hGX;wc;zllGNWczW2z4)<5fNg$uD+>JR!IVa`3&siSM;Ju(1;T{ zu-~zhF3DtKLGWqHBWY#_zKh;l zk+aYY>yifYTL1!060++pCGJ!LD~U7UgiMmJaD5Na5h?lQa`(3>Yb1>bm4hoA6}1*} z*c_9?xvaC(-N*8O**xQZx9L2~xto)$#rHnw7o7F_IP80Zc$Ne$N!>T5GoUY@Rnk`! zz!f${>2mpP#7I|3P;b>zs#}-FQ|bNx4d@6g$avbmfWb-Qv#&tv6g_%?dP8y_cvPCS zD!^6suuSw^rswpWLwU52p4L&_>J<(hnMF8= zpsZvk)U2QkJqW76QS28v4N?BIdLOriceP1}sfzf}{{$e#R3+0WHuuhO42Y;=$IX^K z_ldHU;r$VuRN;Rxq!N=wPpLN2@&f-Yy~-(4YMSG^zs|ZXpwH_@1lEbc=qAaZT}OlA z{{|a_ZdWuCmDhy2uHT9ZtAYm`v2T0LK3eu`=WyR4?4HhI^s^2uAg=^6nFE-dd{Ens zIJKt8+3Vdogc{1Y+%u(7hJ7esxB=-Pfg^wfCkwe@T4XAUTK3~;q1kZjHSOf*Yh0!C zC|;LmKf@MVBsR#AVf?Rk9oHW}PVZa%f`EE6M*{NL`hFBJB4{JFx*`%hs+fPvA)Ejk z%KIX;0Jwgou)2`IzienYjjCJjs5qPHYeG975PdQ~<_o_mG~%>XO~ApCsUM;&<(-V~ z<@F?7?ewp46(VV>ZgUFbT==XHc)hWjQ?HxNn0WaybR$AIqk*%3hUaK38szOiX5R;9 z^)78oOgU|*pekh(?dufRA zYwSm4KmRbUV;x(hd+bIoLi4*4%Kk$@Mh9qj#{sc!8-hO$M+9|6ii6nDN5ACNk#&y6 zF6kqO*TC!SJv{IVASiLVJB2$?Db#;{I%q|-Eap3wzeB>P+*tKtdL-%ct|9{v`>`p% zp3cupPpsboF8Ncmzy9ne9@QDVIaIIC2g#>9D$&=Fv)rEL$&VVQoh z(G&WtU72 z_X`8!tJjWM<$Ln!@L`fW;H%@Eh?yP^Ol(Q4LG+%OuWSGhBxfb5fSNEd^i;X1nE5IS z&Ax4^!(?aJOlnpaJEZzV2I;uXrhMi;;}#E*eFYWWm%}l_iMN=#Z;g>m*v?XpvAl*t z^_r+k9(xy$y@_ps65(HI40BuC6qk7c+t;<*Y9cyDE$a796PHM_8 zj{ZDoZEbsP4V)HM)=Q<^`bDcMJ$90}%nuIm%&(gi{(+(b!$ zg$9(`>QApK4`Q#JW!D>+27+iRaMQJ@E#xTEbOuUSN+u@uIYSaQya(k!!I({~GEm64 zqf*Kh+C_$2u>yXp-!^}p_M#$*Px|fS@!yPfnEg>*p@$=YgJ|oT?Lt>ROiu<=*f!yB zds6d_)|rFJ!;-0>f}o`P1<3Q-Ib2Huidsen%(dkDy|44%Oh66_uzlo49HMe)aqZC z7KoDQ!>Q=1t?PVqW11HmQ8p~=lu`3CSTb;^s=P$xa50bS?8`M!%gtYlE{;ihSUZX+ zg$;l0G(Fd87?LW_+yT<-B(m#-vWNea5>b-QKbXyKrn@WpB0y9J`k&}^_UnFRkOhu0 zuU0&eIx#0S+L5Ah45P2uu;ZBDEPa}uDdVV}^~n4rW~6JBvl$zQcCXFybQASDYa89z zsqq=QI4X}@E0rYXD^PzCx@c?yO_!ygf2pggTJd`M(=FB33a~DuzVB%Q_mI7>w*XkO4ngxAF-nZ*$0c|$FcghZb9uc;U1fWyJ*`?d)HBI< zip3y0-qbHkTSH!;OzNC3o$#ayjM+f+XMRew=O(tC*Ekx)1VpF+?r^Z-0cGp$_RTbq z?$EO#)$q$u2}STL2B~O6lav}HX~J6*wKER>l|Dk}_r2%ydMc{=Tscg9vRB;rNQUA- z|GSA*1tOof&bZWE-%I=Ztx1Kvp!iXGcnC)EeDiy~+<7$g=X!C{?N?ZP$OV}JvCkRn z{aO&ga4m?3nFxNu3Sb?hJrP2W$XQOjol)5?2{y_0>cBGHVP$s27IRHHylLwFusXfXr=x`F z-OpEs_oEDNJ5mtNYlm|o{6)!z@SQVvQn=>UE%uP=ZRpfm+Et>5U_gpJ&<90=ZXQNj zmfCQc3x`>l8phVN811d#2?P0}<66vZ3)}D8;R1*L{nTB*2(5mt)dq=E-|e{cLLD*M!+`5$nPKW$Bw^Htcav@p~|k8!BnEgCv*GJsPEaAjRBZ)5t;5vmfa3f|2p zjl9K^nHPJ|9310J{!G1x8Fl`3TQ5k2e}EPKrUM64xr0w84}~418R2H;WM6;XY=1fG zl?fpfWTD)rr7Y%eMF}O;37q?Mi4p>nwS~%KDa#|^M+iIM%Mci(B`&IE zh2W@)tCFK~P325@UsK0E8T#1Q(9>Pi*_7Z^I9HzJ?b-q7giLiQNfKcTWbvpX3+*96 zz{>rnlk$nLi{lVBOUk1ln-6Jo_qVAsss0++W#4`WshSKV{zuxT1Jtp2Jzmfbn$utFTZlMmT3kHcE8UZ-#vM6MquEfXr# z_H@_wkCp%LDwGz=iKbLA@GyVm#snQ}sp)G6^r#W4+!&sX2e3Q<4M18Sz-wM$2}DtE zJGp;BgP~@6lnbwa{zW%H30Qelq$Qdf8t%v8q(s{mNENYIX_hKI;(X@AW zXt6ChId5Cacg_oh|Jgr)My5V+LVg^8)=*GOiOAEAm^HhnaQi40M2&2=Fs?a))H-u^NmP#(VP);EokrA|TN*rb1hk z2`L0*du9rWsHa2mh>B0|Op|G6^wVqIUAa8D`Aq?DYdao zK%u~0nWN>R3B^qn&tof)M~znf-{dq3oJts7w{<5f@O;^>6E|73Td(J3#c?dd~G6@QT202f?QiX~R|`;e3W>J`TO$9dv^M7Z0$TD7jFT z(akD_QL3>Zfl|9Xo?J#0a2GDw4ZbI%K%w(bL*^7{wX$gCi#u)(&>UF&8+bn_S1R`l z$8I|OCb}3GJLV^r(2L|+$ z0CVqfRzI!+UQLiPY{;OKQ_hbHt|^knX3^XpVcpbuAXkfuX2*xFeZRTgENaIqQRnrE zvstUSN(WHM3yR0!wKiE22vTq7BJ7b}MUDv5kh8Nvd}VTM4HOqAz<|_-M$= zQDmV&S6fn%LTM`fw&inX(5$Zgh9ig|8xX^&f$fUbur`Q-=|nute-m$$`GeKB`jgHO zMHggEYN)EX@T9eRaUA;t3i(hlV$Vj3ou~jSL!&>X;(E5vqg10*dGHX`vHsdmp~%aB zusbKma=i7V_?O7zbT$Xb3&6|4TJa}coDPEM1_J5m$ab7l&W6du3V92E%)Ia6KMCkq zcEDnv{mkp;(FWyPK*x2w>UW+?(py8b&FYcvFA{;XUxt^SHIubSEC3+zi-nW>2|-rG z^yNR%>Yn_ep)v-a&`BHkyNCNA`UjTM|Ed~cq(*=aVnDOrk7^<b#5X; zBB>!y*g8IU|K97AG#its_>^4o+!9=L#*&fdope7tzYHb~6JR8xy2(h|wpbMdGq0dG zhcovGWqm!7q3rL7-H<8sLfjeFm-dL^g+fYHjzI);Sd>3ALH6a+9xCCWagJOBm?R@8 zB}ab4qxFy6@OK;)5;kNwI00@XW1LR$Wo$<$Y39@X{l%j3oEk9!oIaISR!1!WF}Z=P zfp3{i5vBo^`K}7}knF04Vz`<{uUItYW@D`--V*LV(lj#YcJh*#`|0h|&9CGadlHNh ztPhx!zLuJTx{#-)sZf7Pwe#?R_oa#Ics)03U4;l#`|lDK471g^TZ<2TUn#`NkBYzD zH!ZHVacT^3XOQ4}9!|@{h4!mc9B_RbL||x5V0%wj0yU{ES&-m>K9~ZB_QLoSJ&D1$ zmJJzNh7VPBF86QFzXUyKn>Mm>yAJD|+9xL)11+V+B#ySeS!^b{S5b&?S@m<(=k#%$ zAuDK8y|#%N%9sfQxgoe(H9p_h22Tb(_!ZphvpagQ7)W{ovLOkV&<|Yw?gqSHPU(@v zMK^!fbs(?vo5Vz|i(H)sXEE5=?F@MOC6-74o3{qOL{)RMlUjYBJyxnpE*X>u>0>AX zO1GQ$7Ke%5JdrC{hL*qJv#^`Pn`to3Mo?zs5y9G|whqW($qSHag$JZ+g*NLp%1yY% zw-FT_S6efK&IIk$SWSpqYtDs1}m?N#M zV04Vn4#C!47=59`x*xQxiG4>@?sDf;glE|ull-pJD>Mt{u+fZi3eLD^Oz__Im&y*#_rHT83CweX83Q4XBB>iBv_L7k-zn&csT9xVDBu|*<|wO~$$WdWUVu+jT1Kq< z15&LeFFC5|tt7jDJ^)~~a0Au^)Bw{k$cDnz`Yskr%4a3eYtY96Z+b!p$q_#v-lnvq z0{SR3g0iVmn3O1Dgdovi!^7{ZN`LS2OPT!CF`pw#QX9!pTDN=RARcA-VWMFZ z7*2$EO`P@GfEiz8NeXsKJ;-REKBwSv%H}-s{onG!3$E;Y+M0!%zPl(l^f;}UJY`VC zfU=n4prS}m02r3K4Lnlsu_x7#nA#|lctBKM6;;Y{Fl;mF=%#|iCs`4v-vim*TAJN7 zqxUTW|H~2Dys!}HEF*=eN%5bqMIPvaqcCBNIrFE`ixO-6=?zY zWyeAK$zbiLTpXXvif-%t$OTCX&s{7NCCW8w3CsgV#8Z#7iU?G?l$ZnMaKzHQYx<-w z1A{+2TFP0VkP6gqmS=nw;rGRE>C3{6=jW-2!x-bOgT+%#!SW6H#1{h?&{tsqlPuwB z&2;7ILx+(rY`Umh7gnc%Lk5VcPthV{Z`occ@Yfn3CoO<(kd^Np3AUBF=hPJ~77i3b zCoz2J+ErBX!4_0w$5Q1UBWb`xk0iOYGz5avtE|cPRQh|CTDZNfQ<)Q~t7=sUZ3!A8 z%AAOiADJ+dremN83VjULcIgPdcN_hD^6Rb)%jGZI7*BoC!3HmNc)=FMuNfzqd`-;6 z1;^Y1q)UoI2BYdwgsuZIc$q1CC&lcGZVqTCeiCx}iKlVgv)}qCEI*8G3(gU2XO=<{ z_}|V=fi?CgkJ~*VY6=ANCl%1`Lx_1W);t^bw`k!}!;LvYtvDYrvh2Rzar;)XdU}OR zqmoYNf2~tf!>k;@6@TqP#3sG&sn1Hu7B?{QA|l?8h1J;xL6E7N$ahx?knKaB_w6WH z!f@20$k#^m8Kj$^|1KUQ{7 z5jie^C@J;u$|7NgEz=>6hRlOXi07*^0SRQYX9KUAWzlOU?)abAi94#q-W%&ztX@c&e(zSE~QO66y8mSX&Ab8~PGy z5Vq}S+WZX<$t7LOBY2l|U4oIAoUg_~fE z()NEo0{U=t6xwm~bw$B&1F#DDAm0y6(G($|Og^Jq-1)oP;DAy{uB6$zj3 z&}t*7C)g{D6|h;a{TpdpBa~@Ocoip(@l&%vRS!J?)Beq{>o)im*#s?Ito5QE6O)gH zY{6zG2FTHg9#cOYJP@gOPJ)ORQN$6Sw<5FeB3KTTts(A_f>|IaXX7r1_+FVcymUuQ zT)O!-J!K<8;|dQE?XOZPDL*7pq!Sy=P+pE^NZX-VjH~QwJ1kHXxr9NI$V!YNNoe~2 zK#uq8lCH%Oyl%rkWg5F!&AX{Q4Y4^$b(X%NL)6iAf4^hDFoD1UIw=O)R&CU6q& zA5eJ0qaoN*VU|@Mc{%9;A8&Tv1fN^1wJKP;+9`UfOHq*+BHxA#i@P9$w4I*?!EZ0* zN7D1N8MN79@`2K3CcIgSsNb0;A$;Jank4zpg2n|+X}Qp^P{Z#;y}YZD=*s=u2>AbU z0i19OXCfgqSJUIA$9|tbbw=|mgz#0$F%+c298lANleABI$@FK~vBUc2Bnb0!`3v*z zV9T%wyO(tQ`0Js^rHfO5fv;Ramk`Ff*J>F~7fGG2MpW|myaa{Vv){Ax8Mc=HN$^dqlz`!JRhqql4m)*B!N)rJrus#oYP20Jn z>8nzPV`z5FiM6I|&*|(*Uo&Vo3y9zQ=zq7?v=GVXjPRsrt2nBTI&|aM1hJqD(({et z*!)xNH+u9zFrN!m59v!mL*2o1_*|!og@6#uzhS`N!=3W?oEzzl96^ODSZzA8}UH|;f3*5ajh82M?U64!HBiThTqM-f;a~j{7Rj8ZU{kVDa`a#x{8lLTb z)x5181goF>{2r$41fs>0=BIX^eqgHdR1{I2yfBjn+>{Wr$mUoicB8)cLxdU~7 zI(CTfBZmT>Tt22}>E7_FC30C3lUZoag zkII#(p`IzqR0W}NHTM$t7AkkP{Q<*4bC?J zvBj|zH47b&xS@7S_wcQW-Ot0no%5#x7#%4Xu&n#845Q9lk4#Ish#Y>Ow)a*^bF`ol z8fRLyjW(^w&R()(W>)!g$kVs?<`62r)(gHEzs8bF_OHTl_&S9ui ztep{F^jW;CNv?bd0h9c`55DIAT~c8GDLl6aLi}HmGlT)uX}s^Z{XPvemo$jxLhS2D z0E}l8rta(;ssFjK?9fG}@*crDGfTE!|;Rb=_}A>$Mk z`{5G~vhx4;rsZwf^4G=C;<#s!S)E9V;M-pWuM%9K!ZJ%3J@dcg)3XFNB$(V=-}@ZB z77**^l&-mE7O$m+qblqZoxrtO9bweiVvt79F-)*(DCPbVt1LxGYz&SNU+EH8YRpVZlZ*gT>_mJEKUR!M; zh{ZnGtBJ!v+1`;gH#Mn|ocCOsH>*nAsbR0<>>acj$yU1zIQo4xF|4f?5kynBYAn~$ z<2v25%$G$KS*qB0e?;7z7Gx?{6yAi6t%`>isev|~?WXUn`+fJD{etLY4!@(c>ZgnT zbCmy(63Xwub@tfA%$FZ{Kdq7n`KG)z!vLrXP_H>R=;mx9uSLj#LbPP@A@}Tg zX^PP7pEkqCChPE&VI!|II@LSyw~W+5tzcYvOUc4z8fo)(bq zAUe-8i;2cw_Ir)AM*7}A`>Aq(((^p83a!A8)OEL;17#>?n#S#)gW+cWNZUPBTnXQ0 zjoiPp`y%KIWz}Cdr6ruYOqa1sVK!mb&`=gv_m@}m$W6y)ZJgD7-a$^I6MtlEyeDz8 zf5=NCW`TnfctZaeLUa50Jj;RiCs5D%^sAi^IQYAlPEJk^4k0C`&<3sb?HigaTJ8N0 z^{XGQ>w5Q>6_pn?v^B853*e|vJa+=}fi+H>kC?y!-6T26k+oU=b-l$`KR@%|~8@3d~JnIq|E`ZRv1{x&gSFiF#LK{_OByjw%oc*T&1K zNCBpfF-9pk3uZH(k;)Iz@2Ygv`|I68-_ujA6iP;PIF?F_sesT1+!;zgPG&x@; zE(iKIz1#2fl#jMjC`myunH1RkPHT1?HYjKmy@7vNQ)P3!iH`#|J6r3{RlglBc0UVu z?z(}nqiPb&0v~wOQFc)?UOuJS#BLRCAhT0}b(2RqnW z>C72N`0H3!qd$@^UT>#29*94r9ygs-^z!KN?3;fb0Dyt!(_Hqr8>znhTFLh$KoPzxWBes5tjr)hW~XSH!KbgmO4PB5V|no^Ch*Dx^crPf`_2V)sMC)8b(`gjiEar->+ z6fhc+ziU)i&}C{%RUr*nk|(GcbC=uRjx?v01N5oA(S0=~5@;G&`R)b^V2}ZBwVwF$ zwY~dX13Z}HI}xrz=zj!JsBN;fTRB9n_w|=mS}OdGRZt5a!0XgpZTx@^HKrw^DF$36 z4X5pYKNcDqu2w!7R5?lX`4<#S2tNO^VvrHmeQvLc*v?{-!C$u}+K`B%dD)vkIYxGm zHUv$kKph~7HW`}FDp5BDzkJ?b?fW^DyX0uY1C2ut+y+>9t?DsR{OsX)k*UI|*rctlx>I^7&zouO02K0GC4`Y1b3{#VFaRfXmlqK+H(?4*i(2KC%IdSs6?5*Y-Ww9sGN%FIw$)56~eJUm&oRj6vGDz|ckyjrn6)@UB%cJnO6_Z! z(-~bD*>)c(X*WPiC$V~LE3#46d5lg$&g3e5=rZP8fmvOn4U0XLm{d0BTqCd21S40t zH%oht>8Ux|l(G=VfdQQ7>#DgAwLK^sjL9BqE-+2NqV}n0^MoSI{#Fw*z!h^j{MoEm z9Y3G2Q`eBYb= zqg})@hhL+?``%~GGHCI(&a^`}p%sk(y^(;#gJjd@7tQB zx6&?GiXFbLE=Mn{i+JQJ}Ix~6$90fcHp0bJ#T{$&9-zG!q6MO&oBpZaw9zE#TN&gqPCFQ;?a_v&Z4JLv zdZbtkaPBop4WcJq$gn09s)imIIezW_Hq)$Vpz6Lw!S8uH`B8E)sj84)0Ht3$$CK8jKcbM?B}@SC>vJ8-4r`<*6u|^7U(xqe6esnhedwqGxFjYJ8oO; zXW_<5m#u1r{}Hz&8sQ4aXN@mI^BuQhN=pezz-xaXC0|&A-aa^+{>^^q^)-_9W!@0- zv`jjBO1VUV(!z(3T_^J^6ke*ow)czA#9z0!+q%YR1pP=S4zG>yMFCPxKN;JG|8mqyxnGx}a&&^8TAm>J26Qf0v6diXNKU<^jFBNUt_U;@l!S^RoN-IXz^a!TiG zZ_0FytY5*audhgFyp#*U!>qsgbc2%qwQQ=8?!3*x!nbd4LQY_yPVyj|&%XW9t7JqM zZaJ~s@l7Z=pdi^2&H=~uEzX=!kYPs|^?T==Z0WMRK(09iDftBJRR+-nq6j(5er>`j84NmZd`bXL z1WY2*oCkcg@J?@h^$GwBsV@$CloUOqQXZwhGdo%#tg1@1_uw>k+}`JQ{bl-bqo9S~ z+aV{fnXMZF>Pz`-joR54ZR#GGYUrI`V`5+Z+nOto8USCo^$1wjR%vEXY*@z7?qcdz zLd7dgek2OIzfUh;d_EU$+>gEtTP%0&q;lEBi4ap4H$VkKHThdl(iDHj-1ooEB*glo_7K8vrzPO$vmA|4O~ z&yaP4%{jmaxs?GVJpNW-QQ79XYkZ%!z#0)7JpRd{lzveBHWPcm-QQaQDLre>Vr^`r zc<46b$|kf>1T^!)ea#5v_eVc8`cMkAs$p+UAdC+Hm4tLfAcn-T&p#{w=Ni+_!5&R9 zmWpv*h{Y;cXQ2(s*I*}eooLP%p3BKzar7>b1%{PK4f2cKdW+H ziUed~$V#8{R6XtX5y++{i<4-4%vSxRA~Odx94~6P zmj7-j;Rxd_bcgiLmFl_W{ms!0N~>~fy|U-YAe~Kw@F=MSA zu850~tVA^qoB6ZkS6-SfPxTC*d^2M8>#h18W;qi!4eDQtcRHc6*>c%onovIO2>Zl9 zrS+MrPP=?O3ZYG47J&wqnNFM@=K?oby1^$Wxf~A2<6skF-{zt6tlV%;e*gRn!ni6t zLNy@ka1zvE%(qy%bx9BuqnVVkW)Cx_GClDzCH9sckX7wL7S5oPMGrxrbNJcVzQg}{ z(B!I|JhUTyB&-;8KfV;$&32q&Oe#QAqw(>*aPZaEWmKG)&c)zKw)4Co&hUzS@^r9$ zppmCg?4}NXcj_k`IFPfyYKnbt@YvMJyB^vakPW}gc&FU_n(K_f%lP@NnzJ9{H-{`w z{eiCt93l-SWlz8ofRqLa&8_ut1zYXOLIp&>f_Np_B2CIi!#9f4F&erU|B`7cSd{yL z<^0un#X3G5**J73_S!{F{arS9PyJ8#XHZ;7h--(&G!pv$J394lyO9vh;)@Tib#es= z>{GLXyY@Wi#b9;rl6FID#ohzgIQ2BwquV)d4RS3QELO|1;&(r! ztclup3SWM-L1p@`j8EzMrJtATYSaO&XG6CpQfpK)GyOx=odI>4!ChZ)_vzRrLV90U zZdPla2yEN#O0+{vnuxqS4CnohBDME*Y|;+2xS(_h4=mlUUQjVN)AIg-8sdPWa}?aO z+^8>Mu07qPU1PzYvowxlVzJy^A%+Vy#b$7P?_cNT8Z+BTmVp-g6EMmcnfPM36C2Yc z6ndUjNb1sA(_9>44UE$ga)PYaQLck=<0OLgl4>kRv1m4tPC?37{;>2z>d zlA!0VHQxE#o_DYiKfuCyeHAn8m>CV8pd@1V_LUN+JJsEBDU!8WX3rbVoy1v;;49km z!Ec!=?H`O};K~($;Tj3l&q1va{~5--DJe>oXBw*XFDV{%CuR9Rcp-zXR4M3THg`YR z9*7bw1aFk_B-iUukgj<=I4AVpwE~$Yu9=HVxF?a5Of;T2?>y@GEN{@RA$U{sdUrJV z2gf49QW06V^4TI##Tqf$_u@VvWXZ!go{M+X(MPad>@+6I`dBQPX9Kl*ziF-r#ugDVf|B%l#q=l8I;R2O*JhJE?11y|bX_^F~6^?tEVnB|5BM91HHZ zpNc=HoZ-<7E1RXyv3`fmf^ z5KaR9o37?AC5Bhzz;&~W**L+GWyM;@ERnF}u`swDRsGZYIuqnny(aSCYKU`leNJv4 zkGEf~|FTRg5O-C#F>df>^AAbwP5oAmoDmMNxO;gV?^oUjfWAgK;FMWrONJ4gyj*Vq z%0oC#|JQ5kbRmlygCSA;`j6f1@!)74`!mtah&MWb#IY+v(V350A6{|062dK* zYyX*Tb#zD--J*#QDk>>eM&}p zUPJ+6$DbP}0c>zynW(!ZK0{Y{WP5zi{{5NuCeG(Xxbs*R`y_!1Ykt%<^~Xev(C<^* zZeV+-Py#taHhwS63T@m68sfy?fv=E5hB&Dgab zhemz|w2*WIqvlO@tZS8}ct;`V@Hp&JER=d57w7ePvs%Re;lHM#v|{!hc$VM+M~bdN zJWccQdRr*%q<{Zk4^0Vi0jYS=_l@FJY@oCHP{47gvPQuQC8i0{L&am@%P3UDo`$c3Db%QHRbc6vEJREe=!=(C-(TgW9 z0MMTNkj!J42*}(OM^zz(N6z$c)aGs=K_$ z&4#&e#6fhWXPbpV3iC(!>t_uOZ9FQdxtD1{oIuBwCy1BY4Obuq`eJU?AF2?6SNinZ z#|Ge_^2;xkiwf-xR8c0*mjeUR6l<6RQ9)~c-?&63S*Ot9v9(8C&zl?Kldw&%&Wq=n z?!~i^l+YBh9{#Nk=UeH4p8m)Gq3Nr`qI{pPVO_erW9jY`lv=uxZWfT1ZjkOyLAq2z zQV^s|xU5GN$!hb?^sE8K*KO`Kt74BD> z+0G4p#0k%_7GbN1lQ^fy!iK|lJ!HH8fqv}3oy~f6J+$EOr4n3Phd@{s^G%DhsOvhw zyZWz>WdMMn-^-dtDK4caAeeU3k3rcC1gcViEs6kXm<7qK=@S3KDLEfEH?x>JdMN+8 zsQxxv=LJQx9`9ih%B-3Bn#ZWL*VyA^iK_N=FpL|{vS*vCHKJSuMdb~h0M`1KDCnA& z;|<%=)nh>yF}OZhcEA*cX%-lXi6p>XSMTt6rLkhIgNk))oR(Cvjpr z0oq6pqNr1VEK0~Q&38w|-vRw%FQF3+et`=Wm&iH&n;D?tzPD1SeC$co5CKx@iX1zf zpFL6W#l77`ojrbbRgPKG0P1HTt5*97{=25b;q)o5 zA&VxGRw9>8Bua=`RKoTcSDcH~#EUc_l{He9nN`Z8G3{{z>5uI~m5HzHXRroJx266i@p+wjANS8NX!yqiZMS}2zGqpce3Z`q;9I}B!J1UTik9wq>zC>XdMk8|8mF1%d za*%4(`0|R;W5Zk?y#*-mFM#if$csGYt^QT9AbBYFPwS8c(zhFSW1J+W+O z$9}JuRnfruti*pWDI%4+R79__XN4p}dO&>@l#y08)d z4emiZ4PeOe{)_q3|M~l9INHarKR@1#?6T%Hbu1hb9~?h&<3t_yetisF?LxJLJBlb5 z>yz9#NGK=ktYwYv!*Tbt{j=(VYYItHB+q4)PS0c@x{>W#ktZ|Jcto(U8aAi!#)XlB1OuSxkirdDmo*ws0=nV%14;pK^S6A5U;`EI*FwC z-Qb!Cpy0N_xbizbp$!ap{w~?p(!+RP!-x!MVU%O$WTO&fA}gzR1h8*)%&JIA20`{* zoM5O;CebjjnA|9qsfHlO57x{RWwgqSjBvrtIp>x?uYSHK#KU7?(ED$X$U#GG^U^Uh z9i+~Y7wY`}+}Kj@MeFJn;mM6cK)Dpck@5&iJx^e7l%5O;NkZO;qifOX&ke?pQu+zE zQOyAcZ_e`fs`NAA+;T5=#Mv>{El{%yKCw4@Sz>UX(KNQOA`fbO&W3}@)K!q1v5|yv zFqnV0P-kVRYZL?}5TYO1qxk%Lxbc~6H_;=|_#Ux{Doy@MPzm3i`{ z&%9@fJbR=Z$Im5@3s5!>(lN5T-^*IzGl)#oHUIRQ$Say1*S(@mQHM8Wh_}s_yOPDp z9%|fB&E@1l5#K~B4d65xNPc?7klOtL#rv5WDRWX3-Onx1Y_*UFQ6=28kq_U!YNQjw z)39(k)!_5aLPeuKQFO5SVQu-IyrG>vFQVF)74uOncz)~bSvl#8Jk~m{K;bN9Tpw>@ zPKfJ0klSn7D8NcD3Cl5_Kj+U1gVLeLnPa&$66GQE;NPRut&YoUq)V|pV8+6n>A@?tiI>2-3;hz80w1V=|imJ|52S?H+_KV528{eQc~2az1UQNPfjy z%rt0@;F(He9W!Xty-@u~(&h*``ZrLz{N=fgWLi#VcS5Yq2{Yo8QJJ#o9=F)}p$E(9 zMnVe9>1L=jvFJ13B54Vq2>c>(BPTj*gfD1a{g5N}A3R>o?A6jB&EA8Hf)_l&_2X{U zW8d?E${WAu`Mct62Avf=t6ZIarLoK}uj0?5&?h5L7)zj_mP$CCLF~E30@4unTr_Mu z2TqB#@hK|y8jm?6V9Q8wbu0dU8*sL)p6!D)TDZK%bJC^WxqDhx)>GT;B8+O{67@J) zI4>FmL(9v~5xln7XfHV)4|iyCDK^Nz+wq_u^H0s9kG1c;voJ zDl_2Lin|x551)uUIp|~?%sNf&T*ixK^BimpVNTIkZ>}y#)s>7TyG_SNkKvqkj=3sLCI(@W5N!higAJSS zN;0CTxiCFMZ3tZaE~|ISjJ?>Jt|x&z{40dU1x3mYrePZ#7|Un3&J!!R?z|#4NuM?E z7vk3wb7rqsmvMZ)IZ@xJtL(YjU=BlAfUe*c8(4>i@2Qz9X&Zih#gvB@^qM}OFqcmf zDc~tFxb@oksE+G5ZJcP=m3ggw2PtdMm<%T(Pgd7DvH(M>_{yi#cboU@$VYI_;*blQ z#7Lt#w$bT9j`8dsanE4XMKcIjxC~jtlGOBSl`*!%W6$^df}7<6q)I=jB6GXci+2tI ztpz1V9U=xY)wU;@$O!|K7)SV)^8z3CjdOLXBbks9}A@(5Cctu9E zzeuH;l_1d1tw5V-ZRCs5>x_%GDISaBk5#~9p7!lWwB<=SqiGpo&*%mUyC2Y0d9c92%Ht{04DVwxzCuGzxf*owIBgzS!l3p~b1j z!1I`vepRqO=1(=mIf>1r&v;IrXQE*n5{MjC?@Y0-4K=$B#xD8>TWlw_)gKY)eSfcI;NctVk>gQ9D`lLA`U`WaUq$_&J-_ojlXJ4<5RLxL~Z6H7Gf>&uGD)RKC zVD`#Lvz$Ws+jANyb8omkRkNN_iCZ1ie{A_u70W&!U`d=Lm=s(UaoHqm)PY~Cw5Dfo zdGnxFOKReWR%>h#XX3E66e9;QBLi>j;hy_GD8Y;iq&gMB5IT-eusXQ2Ol#Co;rZl$D` z^g8p<*g(3{@&>j>QUsp?!( zYcv5dh&!lwYZ>2{^c*&D`&X-fI9Oa=$pXTSym`lk=0>mt)O@4YbBwm`#tm@9iOn%` z+qwRXDUCTUDv=9hFLIl6Rowg%GB~ray??Sq1NN3QBv9Yu`0Ce1g_vvnv}{yK8RA(n@W}9RpvW98;bxHbB-0ou;p@-*De2I1T6#&oiay7(Hk{v z;{x|Zw^b2d&7e<5VpjZW3H&}}0amx0DV?4-m#W}RIx?EW&c%p~dVIQph?_&Q>Ynrm z=$g9aX8-!1Ewql9wA90nPF|mGkBc8;5#m51?LxlaRz&4J&p-yAG>OBzfbF@4t2e(pJld2hL04eneh znVzY)^JQ;2-I0V)gFUa{VAZ$~|J*9cB?^uXm||$gXNy&12^i+}J~iEUfI6!iQ2Hy~ zuprO=&x6G+;2^d0Dz8!Xz?f-zi(TRSh0;x=5oBv!J=<*UZ9Ltaf;aQYR{=VDG+DtU z%3tQjFtg*Y2O!$`71tce*Vb`C@u{`|k5eG*Qr=Z7B0o;_#Gce6?l%CXsEVd{mXb(e2yOnm^7(lUa(!% z@V-p8?x>vf>~PRWdeY>$w$rO zz^dv}u;qEjXBW$EaGto-eiW?vFyQ%mZ)yRZ5X-p~y&jxygl+zxr(oigZbKp?p?s}( zdJ>3Z8Yz@@NH8W7C5)AMqGwTTnL6sdd1>Sq+x`ztaR1H0CuQ}c?6)rOWS^NswTe4Y zOb*d)+7ErUvgfD9MG8(lMH`cDOs*U;{BvDgB=ZrGh2#fe9SH2`{uMwp@Repjjp~hy zk)(MZ-iaV20$AQDTA+S&H7j=1f2*;pCi~D+wNA8aLpDJ54wu+uBTDGZ)ILpU>-RY@ zqYH!~FJ8K3K0WA}<4_@VUm7mj>5`ke5``kNP8Uvroi`7WgzPC0rg#%GH)*^0C1<*B zbWEH1q-r)xpfrwrHmLGtUwRl-ZWet0U?ZGG>pqebn4^1-UmL65@!L{{?1w3xQ4$UK z3$>}fVm{TEYGkx6Y`nTzVjO2YDJ2(w*12Me=WfpZ+S#c+AbTD-sClz zxm~uMtE?}k{Ul}}3|~`*=?b%bOXyR|F1$Nej{-~fkkl0-X!b9kpW~J%FTF(9a5x{m zSGX|49+UT^x?{JEyX&Ira+hzOBdzQi0ilFpws0oC1*IUe!c!_J&#LSp;{U{ycq|dnM~Uu`v&gp zMv0L84N>wdnmdUcNuZuKaeYMz8QjF5OtY zPB|@n3K_m0j~iDCO55{^+?@D8eI|qFUhh|El zA6vOIC(}>ucVyRJnEU3w@jEv43!3d_)GByS$gi zVn{;^VqmP6Ed6JZLA54SjSveANl^~$l_JD6XLWDDmRy6fN~_l}+TVRGwM$gpc?r=M z65fb?rV+*G=zZ^P)JkMtU9Gstl*9iuh|5$fc{H!$_N%>#ue8uQ)o?BaE!Iwox>i zKVJVa9SSi1p7;1T=Jp%{!_;9})H|;FJ4jxicg8z5NV`@Uha>$yoxguu($oX2?{d>T zmqXOX`0!WuWa=&g^Yha3*z&x!$d-ab7cO@&e=!&(Kp>x|{nZ9#k3=BQKRT(la^=Y6 zdZm#ASnC+IX_j`6Q5N(p05L=OaW4$AekNBc07zNN{SmGy#bo~?LSo%(bd@YZKs9RF zbG;M3MJhd#G)e_Yo?-S2ZJzIahqPbd0S|n=h5T=0-(H%4xmp|-oIhi;D1vQEsge3* zcRzNv7P}1Nvzeqhl6{2=qN@3@B}Ge_Hdl2_@g;1nZAJzNf@llBeDH z9;F_J4^fi`f5R45uK8>ngjxUu&MIA939nR^lM&UY{n5QW!(4$b_)8C_v z{s_r4Um${5eOwi~EA%%e}(=&t%82?CT_UHHCTUKL2%&xiveok~&mD9<0#`>Y0@!KxG@D%d{n#^S72bN^#W7WKIovI6d&w%|MBiwL~IK(asLzt*ZY&#MXo95Gw;!XWuFJ zL5Eb`khfv<9LKuFn#pi(rk6|dfB3|Yc5jyf{n z1Z$bXp>>tC^{((j@ol;$7cJ<+{f`yghzeHK*hM7 z6%Qtqmkj|Y?5_0d#j1@&ZFj`|@;ntyJlT66v)enQ3UiRj5xD@z^pM)<9|@XEsvQemgNvbT z@8q!FJ?NiS!QqfS^O|3U^>kvT3f>WVbigQokSk^h#?@~D!y)i5)m86GP$(O@%Ov4PpHy2c0yrhlc}DIPaVV!B!C49N1)ib4DR$_ zVdvGJ6nbi3=W8@$TN{H=CR^p#Lq#^V{4YkyMLFC9mR)D4`Vem`3VRhL!&t198M+H64eSe{- z-Y*Qo^_=23@>-ZL4%NHkycWKNryzr;qrAtuXvQ!#UDMJz~FYdyrdjW~<+>>EODZ2sm8wURl{&e1kMvhO$Rn$v~h` zo2Dm`weh=}4vWvQ|GPlpB3DImaw!srCj#F z9%Q7O5a9S1z-;?2*nL2_=_p|9ky3FA zGsXR!;%Dkx4APp182s$Ro9w??drhQ9lf&?nOXgpA`Dn54vT&iGzt`m7`k}9`^!Y?N z4`SgpF-(|{(1Wh`MKuG~avw8jIRg#a*$>iPw^$#J==05{9J*L~`jexI6%h@yqfB$Y zof$U@jZVCcqHl6<3Bx5>b$vVwh1sF~iMLyU9 zX?|p|nXQ)Mz|A-jn=bOup9iL;y0g$^mbCx!`_zsLqk}>6xJ>g((E!FUzHTg~x;O!w zCI0Ra%Q{pbm9LRBwK8B&y&8pGugx7V3@@B;=C+s-qvFD)50w1py1r0X@0+Yx{2;HL zLq_Zm$|B0l8Sez`#t18f^SsRrUL1Z~i;dRLmxPQ4g6n}RF>NI#WD*N@&t1l_3vX!i z&suifDc~(vYWU0y-|Rm}LCFZX)L8@=`nv8ucDn4~Ce*@0&+ko-yW1C0%jPB=IcT36 z#P#8q{aC;f_T}UH6mO~YL1+ARLy^ot?b>qefWVjr!)Vh6vH0#gbm!NZC}X7!+^HB6 z0ue-L4PKr6Z%)yQeXG1D03d7y-0|T!I9THERuZ1_(eI!+J1Y3mxWFxXH$#mwc_59o z{gdZ($hEmO?Hm$+yVDai8G5ui1BfP;`xk{5!sTPI&n%w}2Alu06=%@?s^`_wfqc~Ax;GgG6Rg2Ch`kn z|EiZCCw0>N*h*J9!Rh24t`Zb)l?W+A5JTa0Lv2S_f4dS#{?fJYzDlfU41i~7*9r|J z>T$k_?ab1Nb$CAK3;~Mwh6lzOoG0zEjQ36|+I#Oj!!Zk~P8GNl!q(ioxbd1eqrT^w zohj+x?>xQB?rp|4uOBQl*=~dL4{Hj1>?m67$2iH8X0I&;!Zt5mhrE`9-v;0BEDZ(P z4vh*6E%rDw;cJe4&aH2X`%FQBST|L$wX?TGlmhaZx#ANnHMe+#M5KgKJcHSkIrb3n z=iI>8w@XBNMgh+zxlO_65@JmZ_eQJ;1@x1b_6msDjLLATp@)$muVkryml}(7rH-k& z0h&biMQTrs*URx$kG})fDQ*t_8K|(_WoW>cZk8I1#HUmtcbbsFqvLS@4RQYzzTj;i z87U!yFPHDqq{X7tv54Ya7M863IeSf(X~uQV;0fcCaY@8Uz{d$5D;V0N^`X(OpDN=+ zhSDZwpf5p)S(}yKE{r<~@1PSktga`e2QDY_LwtLkr4=O&`!*F$#C0Go7UAT1=ECU2 zeWyIaiZG>;2OdZg4(wIxbHZohl`1E0B^NC5slWQ~lJx()>5bHIEteeXO?1S@?=j1= zmZ0)X;%Wg(i(2VIOX*#`Sx?0m{#w#hAGj_TZ&ehHFOV2(aPdmvTke^iiqSF&7v0F5 z{CGVaJXXK-)4)}Ab-QPqzatg(R%Q<`YmCW0gdOY!D=QQO1kjZDXb$+J_ z)<7F;6hdc5mDCmMDACi4&<)YACsm0xZ3I5v1Ui=XZH+<9GfnswhRPS!g(ji49MM`PMW+p&3t1NfiSGj!3c zBwPsv{uf}Re2*9ZW`d@MiAF(;7k-?s{d_aEwlYFzfm1O!Hx>9Sd>Uk6|x^hwo>=px@iQgQ~?4v^WMSP>t(M@L#{e*5?D%c=b9`)Fc)>6u5-;* z*+^RYhS9q40i(0qvYy8Leu9iIbIrQUx5M&)a2{}B!5x2QTGYLzbTXU&omlhY&TQ)? zE}VR684tN_Cl;WstAj6x?xLXLY2PmV=A0aY^)dz$C?T=oMGPoiCh>Z}?Kx!4>|REk z=vAJUU{(7PmU(QYroUEO{kns>P6B5VaS*n#&v%s=MdKmOsNQK+#{(}te z&n%ob-3=GY@e%B?i@?2x$42b?#^ofE{HFQfTeVqE{cad^Ps)^|St)G1T9j8xW#}R* z8=)Vb2YC8Mmmd}z`(u0qMnhKUL`bM-#dLIE%|+I@o9fS_g(mtNLI*2=kieW7eHUUB z$_=jpg2*%gJWDen>4i9afAcc^7!72M-%6bIe8T3Dq&)OOJo3ECv2&j=o{57QLidc{ ztMYi{bbmmmd+tBHNq+;7&DI_umU@q7%HxkoITw{*-+U5HI4l{7FD}0LsZq^zeqQa- zi5KUOuO}ZX4UN>r#y5(`2PaMFm^-z*Pk3_DbT7$=w^RI!N3*^yplV^Cx+@I1IyUeu zr~mp^O~d@N^G-vW!J*-?n%Ed*07BYRS`#w|e(LdB^*!(gnB0O{h{>h{$h zR7lPu7e5pfy9-Us=IHVf=XX`hN4=^}U9OF_Cmy_aiV&#as3mWZ3*~q1i4xWW_q`cT zkE&U~{0P{fRqH6o8>Y12amOKR!V@htewkoeSdBVZsJyp21>fkGb}lcM{CAy>U1Bo zSx7ZDZPpEYGZf%zn1Cr^t360Wl|pAQyS+OsEBnYWoZ1Ba@7OqKnt_%%rLRrxCQZ`K z<>^!K)ZQlZLFHZi*{U#>oqfiimQ40@#Qggp1Hw`_Gy=Vf6T4lVSKYkU_qa-*6+U?f>!;x zj@cpNZ?tbFDwk2JhB}BmUGgQWY|+EbY}d@v)U-?qSUQ|~B&n1Q>KOmW#;>pGfz2H; z{teXNnybeu=aneQ2ZnXiu;So+h0;?2vQ{oMP}#+8#9lR4jwD)wFOWIFgj9&Ee%0UB zpg7}1L5npr0^c{&d4&EL81PJ)xyjl%Uug5sTt1yT*@1Jgp> zd52DMNWGXH%SpNpnz@j-_Ne*UUyM)ho<2Ohl)Chfwvhc3?v)7|5k-~;1!Iy5gIQeU zU7-vYI3S|}?&&l`$%Ms!&mC^)!GY+>za)Y73N7e8&8qHnt7uu01}Qw|2Y5)5j!cPW zQsCl%R;Y=n+t2BTVV9Uf;+W`UzY;m?^St4h@r1)VIs7ws7v1wHU~}qd^8fx)8rr{U zVc8Wr8u07+FdTVr2{G0I3tF|iYP%2ou4BwUdefhaaC}Bv8>g{*aC9g`9Qkiwblz)? z-{*E4ul}PZM~|lUf=UaM-Pam~^(g{8Wad#aX32HU+0D8^yzy$bST?rtS*M?#1cw$x ziCI_7?FagQ48)}P{P5PlytZKEJ`!+<4yGf(ZewVucDI0h{i7on25%`7aMPqfCA&`q z8i983RES00YTOg-c(+r9M~cvude|!I*7C>_c%@H#N38_B| zd6Sy5%x;tEobqb{`-;?`k_SMb z&&FH(jkt?NRAF`5!A#JfIgQSg<|vNTe-rMF-w7m5H2#H5i3%*we$eW;cGFOx#}2j6 zb85AV6RBKoK8+-L{- zot0;kHpRLT1ld8YtCaP~poe#g*9`V!l?vijN*dt!m3@jhXL9BXv*tw*3AmVlYk=X#jX4X%Om)3iIeG%LRY9(ak`MSu$T3`A2c7sibl$V5$PYBx8I2uq3rAGEjTE3?M63 zQFFOs20-%Z(v9^}raF3H@HmIFBYOX#;(QJ8-*ZnRI}VYJ+761~v|*Rq& z@3|@X?hFBvMHtX&ueg>rUz-yhfAEJeGbDawMff0)?f9k&(N*cM?%;?FiF6uaT1`2+sce!S1I{*Yo!zPxe`Vce9VQLd{Tw zx0^*#)%3USRbwb7jk7e;+oZJ>u;{rRKXOKOVwk(2Gl*5?7p#jEXT{E=ozcRDfh>lf zl$4OsXnpEcEAE1sR;MW>yPI6DlrE@0eClUu=@N1AZqiRttpRiSCCPj}}K_s;2o)oU8ADo3SfxJ9e=wtxgGHMUf_A zTe+!PJ)3i)Tpl;43vlM6SmlbI{=R)1=FQkg!0?VT4R5!<3P8o8DR8((y$DedkYh2$ zhW#F2?tmOnW2~bKq{p2wem|fjP-O&i;hpKKpZM{O@Uwb?L!?pHjX(<%!}Nx?Tow@W zzfpl$ycb7)N8jYwvA^|=m|064i(*5iz_tdt6oE*pQ@h2kTqWJ-HLhFUAwr>)pUfrX z)g#++Oq3H6^H!8gDaeMacW6bf(y4L{zJAqhd;jyz$(MfVFV4CFHj7_RDcDVxG*W=T zgdr<#Cv@x7Prs5seqcg;{qdO{!!y}MQqnXRr6L`!7l=_xN(SkJ#mT}iD)7dv<#-Zmkuln7_zCLn`F3X>y7P#6tjBtC&pZ&k#M&QTBDuS zr5#mD4Uzwf1kH|+GverTT~g*h?qZyj-@Hq{MhmjV3xp$7P_Uoz9V%hDiH^dUKwpx#*SRDhiiM)>x-hvQ6@$jR%ECnj0I6c z0Y#sZ$869Qz6z^v4T?lImkRh7p+K&{@|5y zc%Fw^>1AJ_%OoyTjIcR}=`F*M?lCE!H-Gug;__{E<4z50+nPiBhPhWfUtHPyZ==c< zVdL8LGO*qgRbjw{%|Q=rxWYrek%>6D(sPU5U#HHPPSb*hcqaAM2P8)d8 z?!SPbAM)F~&%M#<&JkD2vl9QiIq)kSAyGEe^ucD~Js!dTZiY8wJ|THsujpkrCl8j_ zlya*Xm3sIFU3jV%rKP0q5J_a7oD(aC?7+KQ1BEDX{xdVWIl8F0uwnxV4FkuQr;;@3TXW^Fv)S_=7@v0Uu=YD2bUw{y{F;3ubZMDK5t*L6 zH&9f|!I8nIfvg!77%j@uu`eQLKGA6`uA-SA_FAfG`S}r=_L(k%0E8jY!7!{>k_x4c zJx@hdp8w`#g+p9a}Tv7g$Hq2w31q6k~jnR^TIM2KePY0tp@q~xUHLkLTN z+t6z#f0`!TLRK)4w!PF129S3n*@lA5UK!AxOJcyrwtx3i&G|1{H1|IMe^*lN;OnI| z^--8~>{N-Quvexlv3)7HkopK$zZ?uu?4tp?&{s-0|V7aq8pkdzv{-NBsjHDL25y$oL#+u1E7xInMfb z9;moFoBR8@Baj`yWoht`@l8NP!TjnN-Z7x`!<$naG4bE4Af90ZLWEJu{-|mh z^v@hNPDe{Pzw+4XkW+y)n6KU3MNatDjlrssDC#`%IDIt(0l1 zz%QB4jRHM;T%-&6x`)^dLzJ^A85q3cC}}fT`IBMAZbc7fQSIPSZaMB~b{O>Pysv1K{1c`|O*lWZCOnDFW ztC+kE zvvWKFJN(s!Tf79Cj#VvoS;)rYam$l({ep{4CiXW6&=)g>#C0B{!b{|7!D7w07u|vs zCsHLg{9ZOISi6h>xM$bE9N3GG4(z@|J1v(i{SlB%b+pVfgw6vTPIU!$6lnJCdv56o z$#c^j;*912;GGtmPIEfnfcaU!J*-P}lg5e(!;bpcFLv?(T<_H!I(5`jV`n&QIyw21jBwhoym&`vfHG= zaVT}h3nf=PRahz_h6mCl5qBlsmccslq$bOmWV9Ahg8boZS z88`4t0RIlLqM;t|*@0M!@7GSy&rf%eKylm}7o>3c3Ac*RK*{ws%sz4ogISA~TF_-` zd?<)j0#2fUssh@o@%2AnMF)y8KKr=v<_aY@L)tbFL|9&|nI>*cCF$La-IF8kN@ikW6m;VkW0-fDrF=WWVuQNOb0Exg2#l zD0T3l+|rOAlPsO3_DwkPG&&mCZvP!#P# zUn=ojWFT#5)0{o$!rQFCpnv^b=%mVjgvb7AE@yJS^a~N$2&+h=INcIfs90NuNfEqB zd=YH`^iYs^?E%7buHpUqgQyj|v>9SL#o^ocYMUhk0vgza5&cwB6>oXfyVNaaYOzgc z-Wp&1R)l;gR41nAZ!ya`zPk|HKejX0O*hx9N!A>im*wxV|5oDkQ&o!d6oPx&jW1c4 zTrH*5!slWQQF{Q3>P}fzK7E>Z{Psf)`7a^7aYMy-!YM~Pt{btkj|L{s?4QV*{#6xZ z!y{Km)kUSDOe)E(ayQWe-wE`C*-o5!{u!Lf-r@A!yMk7~-K^+@REQ>`rJQQ0BUYMY z6Q?0ZO|?Zvhe0{W$u`(TeJI)5{>1j$-g^rH+C(GP!Q9ZE-pvp@cYd z{I$sY3;`zSIinN(07?u)e}ERh;i;r>;4G@efE!foJ6UdW!9ja9L-xCi&-*u5tq|>* zEHaL4<|YGfu|J8`al(>c+t*0;i&++&X>W$bF=eE&Omf2lK^%hPw@wugF*>1S|26`W zgsb0<-2CbLH~5p>i@Q#3UO^`GLi!svhd!)xZ09>eA1>%hHjqmFAH$#K01xdaeq()r zS`ZJx?pRe)s7D4W7wqRQi|4qrL}Ms8`TwhY+GYnThz8)X2lO3$kHD1j@)(X#fZ z{C%%~;S>E~5zL{ikwU-n&A^NaJ7p^j)q`kfdDFKn^pxrvl>u(X&f5V*-aY%cPCt4Fo`k%dsSs48EUnlTpg;4NGVMPt2k! z&hE3dv}fsfFY@!KI7!HZUx3tj4@sRJdQPJnz?LoED%I(tL4X)Zj81Ahwnje0udM1kQlg#SACOOTZ)0=x|1dZOr->nEWu$7fjF5(%hXIRB+kFm^!o>JpL7bV!`we)DrvGqB{D z;56;^rq(^I-rG~-3?-$K?-wmj2Rz*Frab#xSh!EmKiJNpc(N+4-3`d=B$^^je*z!q zT8gWs0)4FjCQh= zkCj4+RFlJ|w26xH&Jr~&#jd&c&ud^gp&fN7-$LHH5qy8zoDceI*4(m)or&!lTpb6p z!-r{M5wIovc;%_D%cj8>m`8Idng#P-arPHAF!h&%7~5M|cU_ME9&6=HqbLfsq7_3~ z%p<_v7UG~c%bopo5uI{1GS)di9kO@c@J+J5zV%w-Sm z;~+zQkjDyW6P>o0!Absy;5RNiT{1$P!brdu+UCJU2uzwmzerYVzl1_b*h?rJlFzqJ z+O@mQ`(L^1FC?fZdFD-%^+36p<&U>BXdyVYhw!?;+{G*OCBmziQNx*ozm*grRD+Xx zG^W~m>~X}->Z{&lKcZC)KT(-f{d_bVX}htz`~c-IZ#=%J0)u ztS6bzfJ}_s8<~vpz6)ykcK&>f3uQ87oMRyF$tyq9*XGYjIqld`& zMp@pRDvgq6jrJb={nP)Q%seDtJKz@A?u?a_$|gcucUEjR>s@r(#_b z2{zw}p#{L7LyYe=RXDx~P(qwD@xt_F5iGV#|LwJ! zP>6;0kQ60j*d@Vv(ilb)Mg_$i6SqTNdOLw>B557)R!_39t8zzlGjC!9u3CXal&s4?X1^~3@o3}?MUc<-!t#F?XsI6wBK6gc;nmT+Eo`Pw5h+NX*k46Ecx7ZCjE=l zzLZZMFdb6rd_Sruvi0k5gxYLwp1NH@o|#8q3_j)0fUSt*Vb7B3Z?7>3O?`eN4b0uT z{v+4@UMhcgJ+_JbPyheFih}SZ)5it;j{dDRhsDjVQ3B_$JU&S)vFI|eu*hle=r^`V zA9TYEuA`%*(Y#3=BtV2pl?LgF2MejYPiH8XJqR=VZ*Kk?B4d_c{XHQ?Jsy#XU*~%Z zIp+Ug2$e_H)m`8jrpuMt-55rm%c4N7{h7l*uzlX}A11U1M^i?H+bpX!D3lcHy>LU* z{T31WG-`)((eNj0<_rv@^=?7M?7&qR&IFnQ_8<>|GdU-0erFT~VWAnM$L2Vc3lNuA zcJd88R@IjC&UvPdf;}=d^XpyOsl>EZ|BgKH`Bl0oEEKr;YACSImaOOT_=?}HE^QF=su}i|_ZwKpK@exk7V){deNRb?{&bC%h zq4SADyzFL3Bucby494ON`O@K%gYy47#ov&8!aU#Br)<@#K@QQq335nXC26oiFE^f4 z^r|+Y*%K5GDl__H=xi z5N9tIMc`(?MOSM6WaoPouKG_QK@`z-l9Z`@)OW-*wTLiIScU5&)s%R7F$%Dbzclc5 zX(02+?0#CKz;D)U;uSq3_=m^BN?0q64TM>24!EFt@s2tNy;9aQN$9vzAyc6_g)EFN zy}vefNxGCJ%sBJ9SCdY_dAZ76Dl>lK+Z28#fzbe5ZN2)K)~F(2N!#@K`l>6F4eJh$ z^{*3_6ERlT?Zwq%?RnfloVrao!OI(r(i>xgquc)77HIJ zh4S~6r%T^X>IeHGvvaS@MQJ%E^SuN&eR}M~_-gAyB_3}HgqV87a-r}0^< zg_>vU=fJW;3H*lxgHgaZsPVr*4A)t-s`6SALu4Ogz9kf+%fGGeHF*5tl>gjVtsa^t z(C%2>TbQcPkk6#ZekY-D*mmdCdPUa$x4GQDw{Cq?g4NlYL41*yrT#N z4b(n1VvDf~-JmDz@%nhHq*J<%cz$66)^*zw#%fOIu1ov@#`GnH+yUStNCucM-FCNs zt>ySotWqg;ix&Cja1>o4I+f}stbnJQxHpFeEmp%eGw}WQnIjrY+jGQ^{_CbURv&Ke z1AH{<=VPtDHQ~@G?t*j~u>!J;%iP_1FWHV@f4Aj6+pQDORQ?BUm>o z(y?zW@l4*RJI6;VClOVfh7bZ{B-N``&eG^k;6Ts4A9V0}__?D09nW1q{>j_4Q`#8T zsdIqa?;IxXkIf}HtYsQSTuUGtnly{M9G=B1v+*z9t>8h{YNjtrj`gL2hAcTy&(q$s zWu5jCa!UF~3ymj{q3?(QzB-=Oc$_gT+c^Y?3RoU_k9`<{C);1>cH(I@PT>ct6G zDr!P#DEd$iH`!r#o1^QoZJMErNRAvdOMvee`$^mYgv(eVRh2N`R`Wvveu%niGiI%> zJ&s!5_SxsW?(vVe-!N&T^uaLkg%>FFdpUc$3#!_0ry+SPZkawt z^pMhRC|(N!!lp!&Un`-YkAPg9%;W@nLfr@o>={ow?vP{5XEHL1p3gpfOXSuQiz5pa zF>f;lKh;n@r{8se9nN2GVnSni0Q6yuilnv!yVC2nJ9d1j82r4`_4tiEY_FQ|ddXou zODnWSspVuPdaOGQx)2(clJ`};E_JtBjGnO0dJcsoPZNXN7kra(&Mm5r9q2SjaQ`D3 zs}09ef@tAl4`RuYFc=t)Zr53F@Nyj@Q*={g(ra-j{_zCA`8=+~$kq2rZ zd}%%hBzG}$j_XPNTou7NY&@bAZ^ALOAYtNj)xJ}+yqeWlBV>j4F*R8~A`FyTO>j#v zgK1(CNb>Gf@72YN)WH=1{%-;i!$_w*PlX~Ic2=~B)jW2Qn4Q%aYF7Ix?f}pGM z6-{)MzOETqH7A_9=^7_CSmgxi*i`egx~VXX2dk*?S4u_^zGAV1T<2ei7otKAa+Uo( zxxDf}Og_-|!iMs7_rNeVx2T`w=&yQ@jGR0TVe)t{kY7x^Gfx{_xj5H`L6N2#io{*~ z@bEEG2k$I?<69tJ>x=4{Z2`oyt{q|+=Fk#qFy4{36eUeGwxY$s9QNt`!tm$g1RxF* z7urPZ_jhNRiyKkst%IR{vK3_W1SNk;6$o$Ai^5nsL~slPLk1%)Cj2q(G{MZwrod*j zBvdE;>}?{8D4-JlO&z@^^@u&^oZL%l^x+2XV_#86U72eec*%Kan(s5#wx_u=H;ZS( zuP+>()SW-+>eK`DO(KFzkol3ql`PX>F2ype@;alaaU*SRugjfRYN>~0{pnr5rU!2H zO7N}t7Q?Z09`UnDP+5O54(VBM)<)qDdAT}V@e}%9!Mp24w=XT3el=Q1U(;YVUHw~j za=*S8>g-4ushA}ATj!2{T`v{cJw;~kKu31$?7$#8^;%C{k;~W?b19whse23VFB`=~ zDu}}5Ow%FdmaWbBIZ)4f%1lUwISOJ3@=Hd-#GNJJFb8IS@iD;EsQ|3iKalG#3qY?YEmxk2HTJ4 zq@FG=IcOuT8XOQbHeCB?PaE z%gP3$Z--fakJjpu#OD=r8L4&%F`Ql15Z4G`E(f>vz`3r6J!dy=?am;O3ZmDrQ~eR5m#f zCjJ7c&AJ#Mvymc0EuJ4KTfa1rHW=Zfr{uXfE)-}cF!gOC!gl%%83gzl=U$pZ_flpj zJ`Zoy>^?G1*hn4=U8;9C`a9<^`$3vD%!NZJi$(c#X7yA^o@>2uxxVHwbzh-4np>uV zkK#v`tKRLmJ~Vyl!p4?0^l=E`n9sbI6%<35Mi2i~!hO*kY=@r-6G{bx{(=C>VKBjy z6^nd(iV&T>$0w^F^Qr=vfMF3BClwnFd;3Ia|Bq=|sHp%AG+Yu>#59-^)q!yV-M9ch zJeI)jgn=X@Q#o#B)=`VFW)XS^YEy~#buS{SBCr6PaV17z*C;uly;<5sq(vQ&vRDG4NS~o(WuAs&JUTTi3x)$)31~PF(1H4 z=;}zYaq{TuWK78oy&M)Tc)>kQgB#qdH`8;vxVQSwpbg6B4foBw_$Fh$NL9`m__vHp~{3kqt-I-YcHwN;#)9-2D1f#@VcO<=g zXQC-9%&FdoclTAT@j`?ER?$9lj>C_lTDq56a#!Pw)GnxgF`DEes7h)oNFNKwX6OQ` zU{I702OK=waz;KF602!fzgag7QFd#}ZF>51a`@=|keIORkI(NpPZJ5|R&ZXs&sibH zM$hO$)Y(w;<2``*3X`ukH1ySY6gK)!<{vk7zW3gn^B?ED_J@0)D0IliH=?4DNOD6< z01Lf>%0)pjkLo<8Lx+WdD_!&4)GtquiJMiw60Q{k1B_|c$7C{l-WN=q(fMOROSqbe zd=LW%&e3dXYPjN!a8SFgjxM0au^rYJ#AFodwMmoOmy^LFV|6t_wU}?USFJh;x2tXv ze5}FVlV$Rly;Z@(ws6F5>98yjdwjDd9NvvBJR&2l{{aaPZ6*SJ=FNi*yD22B^_lhm zMw|Zg;4LJRj{jJV4S)qgv6mQO*`vSi--PARt3ezp?UW@z}o*Tx|DvzX~qqW?_m66ekq>hFVq(u&PHD zh1KczgOx^@*N4y|IPy&SKCQxtEOz+YA*B&YH^I@~V1 zSvJ0DezsY%wf@x0n>lC6AL1a5Qe^X-!GcxN|{~f>?(j*3HC64TR#4oO6 z#%o`+wkNl=b5D>uEgXTy7s}&JtGp)K=~1j@jQsAAOl)2lTIi!+$f1LsHRsT>BzgMq zr>AglwWt0^&j4}4_w0$kbG(IFwB35VrG4O}eBg`^P3&&^^gOiId+pi%J@KJ0hq=AW z`P@o|Y(P%SI6ZJ8Y(XG9FIK0YXo!i#2T>)7H{Z`5T6*>s{B?Zi?_D*47U5DnCj8la z9;Mg8sD~wE*=R~dQ8oy-QDwbT_DL21wcBX&RSjtj2?_tb52%BPJxH!IwS-b2uGCl}u$zj?eN3d+{T2Bb3VOW4Fm7~6 zxPP#b{+CI6%k{6p#*hNp&&Lv>u5BlQRVVRTRmwM|CoTQNI zDP+XKe!g%gwKttI(4|6%6Y`+ZMRyAEePSOALk^|00luvkw-Q^zTcq3W z?y_;+M1U?7q#_6@Irb>taZOK`?z=*A^kKwpU67m}-bm-t+*x|yfq7;K{0+JMer$NC z719S%7k1G_*}jxO*Dq9FpEKajbS;RU?#<=~6uf)izu&G*;@wMRPCHQI-f=gSwJ)B& zC9jYYgE3RUys>{+25KJ50$wSQ2`5t(&mad3qEiQn8v@ABWEt^qqpJNO6>z?9^cs#(f5d7obtWl%Qk2*%n9g7 zoA=vznT}Ny42~wt+&LjGFXj%#TSkwx*8nO4Qq>UjTo1{~JZ}Ffq|A1*SkWb@Nd^t& z8oy3259+O6jA%$?hp4vdt@~$r1RZ*vlrEXK6=pu;hu?-sEG;opRZ2Ci=b~q__fnw% zp)Nuc?9+49YwkxSKeP#^B0|{LyCdWW6w>X^(r^UZtSo#wE!@!1QrR?6i-1s&5*DPs0q0lRcAHeSci2?ig^B)# zUrG#b5!@jYBu&avz6y;HIo{%i-11;vdX5%SFgTza3y5kXYY2yCxmMl2On3IgsGCXr zbp4w6s;68?s#^_A8egE1(>tl%yy5bZ)s+esg!cg;aRPOkAxLLNUMe(!DwQez9Nc}C zk%mySaEJq>lZFYmPhVn`Hoqe!aA<9OC~e%5L3hh_tOZHxXAFWX@}|OC=;EZ+1HRgS zuVt#W`dn&q)Rf3sRgvm|(awD>S{MLyMEq*vx~)@@m{M`_7XpX?+n0j;Z4Q4hPtJlw z95gFTt@Le^B4zj4G3@Ma9E(;t_#vzL!I0m#fh2Kkh%GZ|?W&_u*m*;@C-*jXg-xqIsBrSbhlD9a}-Brd%#4sPO zsiw`;(v;f)&{s8|J2(~Uv`O;f_whnD6VFa{f-YCfJS-P7g}$gGWwTV7`EC`L+`e#S z`)QE(`IPB*zun^y1>GDILzhp>hQuRS8#ue*$!-8l(dXH_P9LlVpeX+ivm)4z&pQEa zpet5L0od*zr4iKh34!P}JZ{IGUtT`kTgWxma~I-`2O~$Sd7$5V*N6A3DUK782;paP zOXuoP7l!^4#oN=baJ5>96&7Y#kRnLyyD!#)67Ah8=-kAY`$G*%)%~>$lsg-}7m|UhpoVy_B6h}KFlBAb360=`&k^{^G4Fe^+>%>vpnidt_Sw3{b5Avyz#pMi@)K@*BV zQ#-*Pl0W|5mF@x$Lzw%0=EXEm8my}HFl^13h<)#J( zy4c79PZd*KsPS46%l(Gsy`yaoRAJ9noP9MCzZn3j6-oj#Iu=`iP zcg&&7%eoB(Y+k?YXr|9|fP!4IyqP>F2y%MLBxAH^2e4OAsQ%GV0bzTyu16)6&+5H_ zf7SJTYBtv4-E4iA;qGy$LfVFi0lIK68DMgmA!PWA*Xa=7YzJ2|)_VRci0h6mlHy__R-h{%0wAum_dxk6_f=i4xs zJe%U43GJ`Y$GLE)mCaDc*if%&w}kmb;T!l}(L0B)nv)*15Wj%~{ahaf6PEC+1?nE7be26I*nsPqz`lNhI@tG}lqfHe< zk<^kQ6D+aLZ$HHQH2o0pVuezx>Tp9p@{eywp92-mb{BQ}{-mE=VZerXQHhQdVF%iX zTKl-?3WD>v;?@cm9?f@FT2@FNW>FHSzB`+F^E+uXGfeNEWAl|w(T5Xqf}w^;1xw8! z%lABdaCDi($iI!?5f6tDAv7J9DP{C@oc=M%(%MzXMI9xu`wgs%jVpy*>}L?u6xaHg z_)^*^2bIU=y@&kE!a*wd0N=mcHClewaxBgP*)tb0@mLM4%5P2Ps>nbtsd|FNzY*HS z6}Du3@p9VltzYQ9iILvAHCdh?R?6%zF|`R&0bBO?clB*xZcszNX9I+&gnqx5u`n8K zw5i`hfH1+pDW&mw!TjuCh-nvv;{tggiQ8qRYp~RFhnU&QQ_*uKV4W2vdp10Bk3r(9 zy}(`oag5{DlmqGYCPytpy(KR@Tj9SWwWkAY4`nqMdv)09E|p~PP>;b{v%nuA0nZJ) zdq;yHCEIr$QMI%yv`DbjezMhwHyz`hKQ$@o20oxFj9Fb!NwZ0bLDW(1e&xR#9GF7IPx$25E?Ss)p3($~wc z#E3R9nQ<|*Jw^9jgrSh#eRqbAA@J8xF{wW|joztRTsV7ckP1k~!QGpoV?5#mhZ$(t zM|sYW8znoC*t$9MWq9sadyQ8R1x>W>M<)>sJ6TEQcE`KtXTpuVMbi)S){}9+%H)Tm z%$W9-%1mXvRo9y(g5p3c7^VxTGuc0`+C$PDXms7m^V#}P8eM8qNUCMq@!%=Gz^92% zu6=l;gzq7B^ouAI*6kVuw+k978U#xAK8g()rEG}!``#PXZ4gF7vTe1Z8twu$1S<)s zF-~f8Zs#R!2h?6nNC-eJ(jKA9cXaG_!I-b5cQwc5(~C74-p~&?yakh!(0R&}Dc%_8 zztdK;9c|GX4 zEX z5kws0f>8@O1ugkV#08*h1V4wqGWUIIABsQVc^OE?6oweCFkKR80 zpS>5tkt+r=dv4Z^+T5%nL^(TRI)oRqKxQA-BapDhkwtZX++9I~D48z<#@hsjW+(G? ze%xQXCiQ)eQY_WqW!bA!bupM&LhpCpmdG)GQ`qTAx>_H4{IKsXK<2orWv&{67l!R@ zn#jk&*G!cTv!kQN%l|rcK;*9l%94qCbc43}qEN+O$EGm0j?FLl$CpMzqjW5gDB#Yf z2vY@76Wn@1mx1y2^D-w-v9G(UKTO-eQub^fkH^Lj28qLPWIX@MOg!~ksmUB#euFp$ zL%vFx2KJXkBc`1hm^_?zP<3RcN4qiF)MRat(my@}N90UjBd{qVS;fcYBwwVc(!94o zxo~5~B-+f67P^aMXtZyRkr=|Tn5JB-B**P>co09@8!r?MFb-LJ!9|V1!4dZ&?VSN&C-F`?0Oe7 z=U9yH2xwlF(32C+|8qPZ%!>0j#>NP_0+U~>c@3_dhtKc;P(X=KR54Rz$nQgyi$c%V zs!)r?q&Z~pPwKY?A;CA^$`Itr;h|VB32*{y&)M__ht|PKYxNb>srjk0aYFH`&D?Ua zfob*9M5B>64T^kxz!D_iJ$T-4bZA|9_-g7rU>_;_fLV-=<3o=c+o=o!jX`NlJO_ej z^hBjXM3PRlq#iqSGQ-3?BrYVl6&dv60Y+IY@$6~zm1)W#*6H_FjOvzpUK0NhejRS8 zm-d8tv|%cQ6$Ry#+2S^~hEA-Y1U_koKaRZmLN2p^qx)c+q*$u`r@dL3OiWGpuIFTN z*jLjrAN)e9{J~jI?{`(t6iPDu8i>W+bOG4=y@Q)VJhbn_H{wyNFAVe#Dv`6tsB>EZBkl$T!_R$^T40tyn9z?`F%*cLDInxPYJ4#r?P1y=u77+5Zaf=YIv|KU zcjw@>%RQ=r+@M@yNDg+Im8Xd7akDUY=NNkDTv=2cvj7-U@01PSc9sTDza=+O1XS!bhTGer6f;(t(*V}OV#POk3I$%6XnK^@YpItTlK5&@Dh$Vj14 zDdFQu^o^{7kiS#d4H4REUb*G=9(2yKO8p6ue(Q^7#ZG)SM%GMGCO$hSO`T`V5jx~4 zy}m?>(*}Rzto~q@H(?(o8U9g+%)kH#Hq+N|On6NVlA9Msw*8z=0G{$uak1uKWUbp>GH?@vSdR4-|$Tc)B|Y9#ZHHsYz~Ya@_?XAhkS}pRXLS>#va}Xa+H3p7cxrI`*Pqc&kJa^z0b*kco=lNDop*N5u% zWkn56)7{Ym3Eheb1Hp7&i1fh)!PLXcTJhaRwnF z>UU@Wh_{tg!}Cc@@YY4cTqYVW3_|$HN&Mh+ypSDGKRL<@i1SY0(3rK>Sb-^XRR0bY zXz-jw1G&DwJl)ly^6Ae0-Tu)d%cZ)TYhI4}7yOl%Xhk~V1Ic|It znKWZ69tMcY0=q$`?D4}AEOGP(CzD0J+Kh&!w+li4X}Y@P5l8NuhLk=Nk{CV+r93y(n_OPG@z|#CO_{=OBtdf)X;Hhg$;=eO%N5qWn zy*pS^HX@X)FVy)r4nit;;D%1CkKaZ&bYx^3>fi(W43Kauj$1K9w$f**wl+G%L z8h75u7T!pIHPb#iIIcWDyuv86=DNhK>375$%v9MHtoBko(*Tlyv_Z$EG%Zkr@ zY`{+mLO<@%qK4EA;%29QA~v$rN@!zY)MlM7@a=LR*CRHLK2FvL*CcsaUXs;cvDumb zgnKMrBLEue6dGxS`5?L?3I1ZFOPvc#q*Fl=r1dS-Orp5Xi=QpvUKhG=G_XW>=p<@nGd!F)~+g#-zh~F>8P^(ZY@Z;c{{6SAuFr= z4Qv#gTJS|x^g90B=^2(QC~($vbBFbewaT1&%{V^?1>P|DegWBb)N81S zaa}Z_=o0uZEFE8>N`GX(^|d6oR862R@@?2{pTY-F_@!3_0*%#`*kBd|lD_ z{qde0sC9GmdQ>&6|L8ic?pota{;mFSM@` z={EE$fx1uXpG!N^1EW?+z@rdMS>q4vd@oBPY4j#*=5LmQH7!XtpHy6jUl&~t_~rlb z=LGbJ)Af+IS1YDF#nu~JiM#Bb^ooQEf?4rW3jbFNK#fxp_&AlG!Zo+7M{jENVnh1& zNXcu}Xo#1#JZgz-*NFM?hroYW>Ix*=GoC^)q_*?$a-}u3fm9U1 z$(ds^_S|p>ekMNL>#qE&H=hA3DLzASJX{o<%Ykua%izvnxK)7_2qnDY+?bN{z6r=d z5{K*DDGDI8V&U{kmspx&sH#Bbi%G7}!Dp*rvEl8d%j9skBwYxW4zu=%h;;)aHPXKf zpo9kSt+c%ejKived%qfNr>>k~W`-E*gQ;~u&=-i82t5qbPK4fBqM1OBC~_*$q($hN(} zX?`oc-NUc#ufI%TktF@qQL~7f4Sw>^Z~RF{DWX`Y23 z);Da2&>R7cC~gA5lG~;Y9K|sO4j|9I42qm}^z4r+FMG0?UE7t93a`j54Pi?+cmDDv zHHG;`{r>X(!P?V*27>681!w-apRx{XjQ;UltM^i6l!*WOop(6&MWv)d|0F>wURJh6mpsBFIk z=lGwd^qU@FdcPpJW#_S!wqMKqF(nLB5|m3B5>ghzOJ8WAf8KwUWqW4I|FY6h2{0mv zGdSigB{0U^!0SBzS2{*-4QO7c|3{a1FyIkb^Qf%*TIi%L#vklEu@TKe~Z+7_Vv@;3|D9fupKH{!&$8FXs(67NY?*Q?o+%E_sySj zHLB%@v7lgR!3{*LTlowrZ|x`!ZtgW@P(lBHA(RSOKp97skFM6GGZf0|y@T)a%$eCh zWl%BUDGjq?P>(Hv32f~nSQ!ON{g@#5{#S)u07_bI z2yuYbb*E5T=$&d9?*a7CgUmMv)4m#=0I--w+>baAfl8sP>9{NEt$XQG?Fp%nTJ^#Z zl#7=^W)!_@=r6@^syFSG(l-9I*!BUMKylX=`=J-3tvF8*Bf+{Zdfs*vVM61`e*Xe# zh2bLUX4&vhP~SN8%>s!*54=L}|2bm^(rte8fppbcs@>>M);Rrf^?^DAeEJ~5n4dM3 z|1h#d9H2`OYJ`3c07vwwFArOSM!X&!dA(P*Yy15@j|Bn0+a;Ld)h2kPW1MFVzkNgz zO`<>1-cCt1@H3y}!AMM>BKsXNymx-Rty(M$H89H$0v$%yrTqeEGsLL^S!4}H)=})J zKnmjl!+#;-EfFkhmFM`v^?s7Ok)ZD;Eky;NL-!zCzrc()vTM~W+21%q51=WD)sMn5 zvq!w*5D`G?i8K{66*!YDo`NF@hT|beuaB!PWiI=7ZC@bvI$J^C-S!I+K)oyG?H2nEm)kAJ3oKry z`)GL2wM?DO=kFxJ!=7s`718z27Y25@M~-ycl$}3ulSZkUPRAUqV?70 zP2zHRRvE|3u;o2c`YwoWvJvo1_9BEbnMr8zOW7K8t5g5S4rD+~8;s4KpEkl*wj%kM zr6>P%i*_d9fR`j<;g0EYj059pr#lQCkN^}LHsza*`b&S2Llz(mV-(h-Q6!wr*1+YC zH@e_9o%BkuH7Chtqf%O*8xEXiGdUX)o*04_OlR~az~#YF)p9sAXH*B85O0mQ99?hh z6wB(Lfm(h_ZjH@@-rg^(@l$D83>GdSd^wA<$0(;>>p801+W8j|S}67F+K$Sb<)Q5Y z4*RJhNNzgM(VYf9N%7%UI#yXUBXV-)7md}sFMJ@$__q&RNChrPu)?1ha+$Ycj_Tml zc9eK1&enJ{;T(LOW)r@Trt(56Cgx>We_7JBc1D?!1P5jau%*0{bq5qaUDvLb3x}|f z;@<|z<_xH+Ba8Xqt^qP4zNaajEh+rrF))N~f5$3C51BDTm;`T82=70XD|zE9KhxUu zY2R5-0sdGp^;1uvl@{_DlPHdY9gdf9VU1z)-(w=^5vLTO0=C~Mw=jmxGB&v&**tHZ zt=r~^F7ICO{M`4DixQghzRBj|q$~1|@H#al)art^?jRYbWrLA1kwdohb|E*3f zQu6%9^<>@hsiW&-__6G}@9N!x0Vv#M+xR6|87v5E@~BKHVpg>yh|zx;bMbqaI;=+7 zw^;ZNSAU}0iWq)MHT$>=U9`*FX;a5?oHn{@F>f zLc4Gd{7hiju8`tn0CsYvC17W97(Y>FZj&?16wUiOuXu%pBo=NSGa0oDm%6u$Xfn{P z0Gva6I}hfO1^5yvs3$_Q+g#JMY)$R0TyhOjRljP4L1VAs*hqiub-_LfR*lW$BwdR+ zFG-cxx-_kH*?xXqb?M8$S0nCH$lIa_W^J8oG|r2Gj!2=NV7kVV3SxB0XOS5U8^ zwyFOc$VIdMt0Rn7R0^fo&=9@7X)gHfcXGyGN|COzF1NHN1fSj<>Uo2bOF1)(z&XMm z-KdE*Z*s+IE2eg0`u|ib7tdK%jOQG$hD5(@Jz1$v4c@6tl!Su!IoFjjZPJ-~Q|D4U zrN}FeK8-)QWgq)rN@$=z)j%Ppvt~Qg=(a=W=@ll@GODjoA?zQiR`yiLPU-FkA*R5uXgHgxVvK#3 zk~+LUE_FksW8tuhqNM*d;+#&((7fIz4i+M>lrq~Ws3WRyx!4FAN=kiCWwFW-5Zw7L z=qb6z9Dt!68#V8*5G~#=owgpZx>=e;N}Sq4fa@f}i}Myr_@V0xPpQxGe90+e_ON)R zapWPLR-q)#XDs}&_-jzWdu2@lsuZbqFpdMJ5no>m%XJ0ue^gcvWG`#km>|EO0UPRiT@T z`gBpWz@QRbku=~HnIx#Y$7R1VokR70IInKUtc4spGtR{Y66f#C_k1(Y42H;z#-GRe zNhpaJ!oqB5HxNF1AQQ*=;2#a#dH!Xm0u=fjt>=0&X}b5kdw+&O-1qj(eL{Tn;Yo0Y zqIz*i9YRb}xHMb*)%(!m&cBqADF#mFr)n;ZgO)o3UjLgaWlvd{ULjG>g0+ zniq2<|5!EyhP|^0mS*U_YbM6Y^QHHRQf)~P91j)Kl)3hp1Ep0nK>q#rpTU)dU-|Qa z;qM#LE3hJ=|40Svl(qQ;-;rWF0_W|Z+W=kC*tdW)EUOxJ5#qXXFL%775>%- zkom$=W`CoLiRtM@`?)qbv%;3$VqE_xrrr0;!5;x@myXnCGR4LaMh#&4H1s78cwRx2 z;cqeO{S)W*-`|y?4I($I4vIm~AM%rF_nh8_q1pAD^^s?veodi>Wj8ItZ(ZjiJh%C` z2!5DMU1p@8I2TX9ct6Z*VYa*`2njugHdo74{>?Qs+Bld!Q!ydH&|dEC1nR7A9f{ ztMF?~zQ_%hs2=)MJlo_@*E?`gZ6I>!{_#*18>~}6N?L`n*VU5NGb9;QX020qp8)^Plb$0z)O-YUqgM4ubQDtPJBBJc`S#8h`Om--Wu*t3fU(}Zo7Mjc1;nZKgBZEhdAI&>a&;v= zD_c@KDtr3F(S2zgEm>w|KSTaM7!txmapTzV(~Bds2;qM?nL#xcoGWYv>x<&skjpvg zvH$dm)EPqjh6110-dO1)Zyf(}@YvCYka<8N)}Uw}gpy;BX}uMaTyQ)>H%I|JO2N^) zd23oSy@j!%`U2G-tO2Hj#ZQejPtx8S+-Yb$spdVtvaE7fPJ@qzoEfG6t&ERPU}p^Y zt2k6bj6g`ea79~aw9}arPFPHU8vO5?Dt4ETYo>bvK0QKj{`C2&DB<4daKGsM zQ8sFp0{N*=9?2tVHA?X%Tm48PLa!I(z!uUX5<>{Zk7{;cZiC1FV?6SNIvMXek-YXL2mk ztliU&4F!|9)X9-Aio357I+L`ZSCjkPdApz1gqv zM#_~}BS8|57P3_9y{{B5hm&|pqwmX6p`4MntJbRa59N(8TCBtrc+9spFp|;o=c3-BahG&Tb@=DI4t2+zL(hF1d+e|7p>W(lG1a^cAH5+7qmN z!ETt6t_c%+Y0Fbt#D>N9888uQ>5ZyZ6cWUAI%Gcj>`L@1$A=;+C5C}eUZzc6u~g(T zl$;WF(4m0B9bCEpBb(g*3gfsAOb;XAskfH zps-&f%-pbU{xk9eGc;}8uw3!ylxEMcJz#2 zdrem%v}xRw%j|jK>^V=t(KHGqLZACBRfQ3G+&50{ONULmoYW<}bwNDcy`&ZclTd&i zuuxhwb7yOF*bMz(Y?CcUj~tS^NK8atWy}%v*fK5P zg?>LM@RCTkYf|bD?a|MjRSROuX?tb~L*Kv?*GAXz?DCw@*S4!frKSn!{zN|6qq)`X z^}?2gRxsO%`Yj8nXW_E_mxwRa;x^mcR6zKwnGyd zJQUdm&;lO3q+&-&Gj@lQ1c(s11LdAe;c=|YmU8BX2%@ahj45_64rbY>J#>Gq*9_ZV zn2{a5?CrY5SbE(jN~gmS>n9HJ|7v|Y0MqqfypPIy7fuP^O4l1GK-459s!WTDv`>7% z@Sois5rKjKLZl$jSRL=zQkty2RT-UnTHir##Es3PY#Nj-T06Iae&2?$4sWxv3~?$u z2OB{%7fWJ$o4SQa3zv@=uDXgZXoY3x`i}HGee{d{uqGCoGB$`At*ZG$EnlLjtPQgVO#XRau@P`))QP@Rn{crc|juElaw?QL4J=tts@cYiD2{%KN3q8PPk=PIbgiB z*g&V{*thA2J@=9+48;E;2@Hs7$4h^3aaz_k;g{{%1dc5nrSwud;X5vzA?$A~3`*m~;`_wYW#d=yRe7txAHENU?T4Wf&!% zWf<>8_=Mlx*M0jI?V^fuqigZ9imCQV`;6`aMAhg_B={lhM%4n2C`}Agf(27_ULEYq zPonVCZ-L;`jnWB{FVPDBcsW8;`{_@;hN`Nk+7(-U^7li0RLSfPhKSMMd=F@O|Ber0 zA0QOqc8(};;c`yq3zclFyLTv)^Q|1BGo8wMI}p$Cq>|Mb?m1r@&L9*jg!2rNU0IOb zvuM8~MsjqeyJg!z&J)S$Mbn4Y^ZNP~l(3N`QWZJ0%Qf~)Gfx;?ALiX`{}-Si<=RUG zon`8tA1;n&6PhS+acCWgap=%NNA`lQ;WpGzK!TnUgb97^ANm&kaIBPe$_m=W@$I_W zu1&Vsc9Nsca&;-*uGNUn`k_RdV5gDRa+0O1EOi*~#7^*0U`JGRDDIQ6nAkgt&A|Qm z>6@~Y5e#LqTn%9g7AF6Kkl8r$OcGo1nVT{bK9;{krri=9df9;g0 zW6G~Co7OCeQu|(5HT1p@&^O4Kb%k;6PAh9AzUv~}Dy;oewSz?tewsnax;ldN;pJx1 zH;0G>V}<-H`{x8os6(3ExsA63`4Ykn;9kFo{?Y~ zApZT4^uEc+uH98Sn-}hldeditYQhPM3&%9(VBvh@VD0?Mx#TbZzwum$#<|N*xlOB7 zTkHlG%Co^TLr){iBoey=i3zMTmxg=ZVL;TS$si-$%nytImDf%KV5^VjPk0uVPsiPM zFAI5Cy#7#966VdB4h{ zXbs?L-}@*{hEW`kz)D1q*t5%lX8GHVHgT{h!~FfkKG&pdBVTal<`N8J|tj@B0O?{o6l!9tQ%q zcW6FhXE?E3s_*QWG$=ip?$lNUB~U^4B@gIY={4%K(IfZa9fW1>*ZG==M0fB0bcyX6 zx)C`moK00YVBqJgK_GL4HIwvn&WftqkFH4S1-&CT0aVjF}CNCF(aoctDjKT zbGu^ZTu+1ih6gy6?(&6yHbHh0Lp=6_ii4jdviIFr_DT?rTL_?a0c8kV48%q`+e6#^Ab%Lko|8{l@8{)&A>uQIkrx~2XLPV`3O_V~bqIMeMuULyh|9$HR z2%#|7LfJn`TGcT(kPn?8@vy4u`QCqQqT?7ouv>tqO*C(O$Fp1Sl+6kWd8>RxK{wfS z>lK)gw>*^npK5%G?K|A&X5-vNgXTuS;A+_-)kwpFB}))3`@1^_^Z&TSX?H^<-ho97 z#Q;^?ZL9NkbC>5lK1WkF+;y1s)DL{T!U9Tg3w)Ayj{d0s3UxZ%lrlP{|5@}lOMzR2 zL5oLN%TgS)sPQiA_gFCC#0i!`v9;R%n-Zoa^w5H>YBE@7hdX1cv*n-0^C!}0?sD?v z9@Ealpww~B#^MJ#CNl)NXq_kat7gsH-TI4x>%Z5Jz`kMt3_<@X_$P4k*yT5cjFwyc z=QyEyq{GaVw%#J&Q4DfsaXv3jwEU@33RF{moW$UFKM9Hvlt?1Jqtan^yb)P9N9W^8 zZXs#bRg^mX?(}mh`6MaEv}cNxWIjW$;ZMP%xV0t!@X#k#_snHDr;RIf= zm2NoP^$cNo_dW$2lgHFYRR54&CVb0w`>u0B=0hIkH|zI>VG869cZ*T=Cd3?569yZp8=fOK|CSCR&1decnKYT+?n{DJ z3OeDmLG!w->Kx~6hUv*)w(A2lA4id{e4A^SGxVzhQ)*+i?`aUmHAP3u1fV=!mi0b| zIy8vbKQww|SUJ9k;_+R5?(>`c_X!LEYS=nc?=a43Z#zoyFV5vnb}%1jzSqtfB8Pgq zEcX@HdOPd?N$WEZ3VI9OQ!#zFhUNKX4f@5jf2<@6m^`t3YT(*+AQ+?CN9l4c9anO& zb6j!s;-?iqfL!RGtecsJ<-WG#vGW~v!>c_f8qAu?dI{eMj>o@M(~m^A=j7X&d9}kWh|b$4@ny*Nuie9de432QAYkD<2MNk3 zGqUrDUzbC;4Ki##`AxVwsWx>CGWr^b#274KI4f+dsl3cQdS7uAvDXO&fD#;&9qv!{ z)+psdgr^I-+3}U>KZFGM8d~-_iAqY?KUZqLsiLeu8<$F712#I(Jg6lt#*n`JDHPQB zU|C(ZA{_^;%2)Uuy83cfZ6oZpz|4uM=t>Z0Ba1r|X(D$0XoO67-oJUPrz}}`&z}l( zC-7O7|GL}vxOsB?czMIN$B7s(b*a@&;E*~m2mj3cwpnX8lZA z9U162QZT(Z2xak1PMud;JF-CS4{34Y)!<XiM9R3DNeqVFuQfoI!{3YoQ!zPzIYvH9;Co{Mw*l7P~^;E<3hHNRFMt0UFyyjtm zrqq4n%8O`0vUytC>XKXplL>hgfK>W-y1)eRIWAWEHMu&L)P#G04G1$`pF6t+psYvD2@4#IQqcwdT46*dX>F7IRmf z-`ZOmm&zWRxn3-FN1LvR^1%Ps|6}T{0_xm)u2EzG3%BAFcXy|_ySuwXDHL~icXu!D z?(SY33KW;(c2@V^@Asc;xLD7eGs(!vNJ1$Mq%tJ>8zlwNr$;39RZ^XEk$J*V&rjZi`c&KB+e!JTk*hv-M%geF=H7`pVg258$XD{uzL?Y9@ z19C7{1`6U-QV;uPUT?teGxW5{Az)6U@q|wS&}(Yn7{VDdq{HEtUGNDT`QfKgVIkGC zYxe-0mbhvo{Ee{08|xR7h;V2FXBs)1bhYwIDj4zd3T%T_Nt!$?^ZAtNFj(P24(|_Y(uOX_U4D%~x#y7EQ z^t=2Ng$y+;8gU+%iMY*|6)+mgygzOy9)ClUaB zkFMB!%3)y{MdI{m5)dDlnr>f{U8TMbJ;wo`e9hl$_$J;fh7TX; zFLuoHl?tJSus)>@jaOv+pCD*x2sBj8~TUY-jX%iY!aGhWht& zu(=>AB+9IT@HbGAUok$ptVhBOzyBKk5B&?>p= z+B=XhoABpUj|J^kRQDG@xKQms3UD@qV7?L)OCJi`Ccg93PFBy|Bz z9@3pM&}`d5pz)sV>J4sqZ)o(tiKZU_6PQ-VY9X!j!@HyBdfZnA!t^}}6G7+O>VMg? zqAUb+MllQ2peXzYsp$%achU1kA`Km8CM&4?^5FZ#KV&PQqoxWGYJoe0K&)&bi4-7d z(k5oiK-S+YVZi%nUk3u5WyMUQnt|M{aN*=D<;W}JvW@j@&Hdie#C49PrtXL|Pg~!y zPrco%Qr4xX%9kMc`=pgwD`4v#tEWGc8?lx++27^gn>?@3%dEDKG#0?r(3r!lR*<0iDIT-oPDQGUs%kvx zas?#;?@(s25WE(}y1BV|;XxhTD)< zHIs8i)`^?<8jK9U!4B4O#b7DVGB$KKwWnXI-n1g%(kek15M)_(J6G2m_WT>nLGDbp z^K4=_hEt%D*{iRHtxW~s|Iz?N5BZb`1g$8fr!%aF9hAl$fP49KO}j_=*JsSe2&xa< z6-AxGK|iEf9$jmxmHLTglhuYbV|0ejuuKAEKTG{OMSF39eG6gB9`3(CaVbPb3@(Zt zT6yx6s4CIb!?rR;nu}YtlD0(StF_~aI;Z7oY;eTZy{w9K-C^akS$W>_z3~5Ryb6v< zA+avu$kZyX!zV$AHrTF*3^`FkHbTU5ShZw{%y}Ai{thr+W71j#z|U^w->+L<}qif918H* z`y#c$!)GmRyb!%7`g1UrLz=omirQbvA5Ref4;I1jfCmhLg#M|8at6k=2ry(-Ag9-a z^;@&kbrHlV5ouiuypiv{G=MapEhkhT2aZiVEE1gV`T65HMTfjZ&N8aiKJ?@MC#8Ev z>rY(Lt9`|sa%Tw;W-8Oq$KSc}?b<$Qp7?3

Wr{*bYIJl>59pVRIHfqV^NqQ(NrhjCkE8ABF!onOX{1+n&SNu4sW5-tfMR zMD6ynx5ujCN8V$n%SVNom7+9MLFu0*>KE<08->|gn3;Dci?!}QLCwW;=yB__ zzkUt8n(sSJ$@JuM_aP$p)%5Ct_D8jos zsuVT6oII;!odTN%d2h&&6S?wR2SSSM{p9hF-(|uV8|Wa5@(k#@4crS|Sy#Lf2#*J- zlU$3a76SRc8X*WsH%Y1*MS*P516;+NLERc1yJ)3h5g$osg}w{xZ=>>GuA&kU#qHbu z?frC1P0RO=AF*6&BG61hjox$74(S1XCXuONs9*cdr*@lc77+r64v`gJW9-v%AbnV% z9G^C5FjtfgDJemYrxHfu6+Ozwbby~59DztHQqz@RsA1R;g7={2PMBiomp@PO51U~2 z=@~8@`k~Ln(i~ToH6u2ID6%4TQ%1muFl|g>+d-!t-mY1CtQGE_kKjQ*L7t6Fax1X4 z2R+ZLNQaYQcazV7a)!R%7u<2(&>e}Dv%HXyR7=$OVOZ=oiApPP&ouZcp~ozs=b;DP zp0N}S^S)gsW}HC=^h`Lc=pMFKbdn_u9~LnJQJ?-er7S9u@-7NC#!;?R)_PqB@~?6K zU~)eI2T0myemw8M?nElTh$cyo&MLde{Pa-EHS`bNNhw1#Sz`3c2~X-TZZA}Z&VjWY z0&Yy1g3>daB@0U9e;$StbF)uzC0}>I%X*8tsHGk%g|Ba6N zvnX&_L=(^l8d=4R5lSSePK@&Wc*<^+AJ!H$tk9@QRu={iPiYa&iv3d7zy@65oQyZT zqh2#AH?3p4_c{5laIfps(9&8r~S3^Ul zt?6nWMvwE-Eh}+7%)hK(w}f32^XY!F&gdU+ssn1(FaEwdkn5$>=sYuW%G#34vbXCK zc|fa`6rmFgZ#X&Bxs^i<(wRJ``X$;0wM2!;`T3>7PzI&JoPPd%d6W-#j(t;W_zIV5 zaoRt$wheae@IuUI@BB80H?hPjfV9vbh*lNoZdAWhVCon@USK3usA6{5+(I$8OSz1P zd?s0tjR6A9;AFv`4JCq9q`LET0NF`;zOIYNQaF z2`{d~Ckvdhs{`AfH8?%Tw{I`iMiUwdz3)t(M(_kMF>?+AKB;t+a=k)mrJq(Z!B!f> zzn%{#f;55m|IYomeBC*<7Fqk2#bp$5rqnt|+1gm{*P2IMk+J&34BZB8R$ST14AG_S z;(V`{9xnX72FD<_g_;cMX3S#yZx=B$o-dEZ4PIVTkRyssd-g^%%H{@vD6*XX<-P^SRV_In~*^fSM%v=Lii)V_E-~~ zt_VuF9LM7Lhhsp8^KAgi4pj>g<(_G#Qf2$pllzYn;er&t!`xxH#Yp@hW>6eD4wj|X z0>sMKty<%2B$?65Gw6FL_(=a#wG)JBb+CO~!#m%+^!Bav*}iOp4p)b8gJIiEIF3a{ z{+m%{;e#K&T%`!%GY?9C`X2eX1n+Yk`{n#c<-WpG5KhOLQ2b1mZr8}#MB2jc0$nce z4T{dkO)-o6$I#a+PsYUbpFiTr7+bgV@kQA0h4KB9TX_`wCRZuew#S2Sys~gPLt*Er^mW%etIpY-A>W;H<|^q6THCz{_^$(+_>rB7u+< zwuA=LLQ7tr134+oMW?k&VsKNaOHx}!h)8Mp30s#L^#{v8{DEqP6oE-#Lby67d7A_C z!kN}`Vd3P|R{iOG!({S(DV#pV9*4f(uE;vWB3N;~$fb#?+p4*5$Db~Ko*LGoiyT<| z_5-5}U}a4BY<$^ae|pHuQx@KF9|uN{<_YY<3k})b)g604WgGfJ24@lXwCOcFA5Dtj z`Wc!NQi9SeFLk%AJp?j`ZC5ZLuYG3Seo_M_6U_4;-OJyIv}DKl>|!OCv%vKyexef1 z#77Sk8S}!56?H`dA|=86%a9(0I2GDfVTXT~OPrt+Y*|=Yj*#Y}L8HM<9QNFh--48p z74UpEJTzZdD9oAto!A(;y;M?}z&ayh1z+Htp7E2zzEHzOL`THz*iAX(6U0Vt4?{=p zt#7%dI1(4u5is|c0{9b;6Bhb%5UHaIyvKmTLFNNl4k z6qKspqxf(lb>hp|0232q#z0$g>9syF2dM;!7U7{$v1g6AEb6SSFdaivbqEUP?S1IFuO}8a~KKI>0-8Cf7o|3#}2b;PcGd zbneT(Yv*hd4G~i$aC7FfX98b;PavvvDH{h#1qq<6 zSJcw>2!R8=mg{XAa^dcTg7^7I+>VhA&y|4ba|3wGlb=ax_f1AlODrN4g8xh5al#l| zo8smAm+qbn?(AY#i1s|~p;-IGOW$&ky7fCFXh_c)`5VJ$&sOCp)g|ZZLWU_&*}bD+ z$}Ys+<0r8?7CNZRnFYowd%xqFzYlw`nKWQDZ_*R#T77i%FBc<5YDkgedURE?^6te_ z4}RTZm~4u-_lWYz4jvuU;1Tn5)?`U<;R$kL?c#zXyV^U<2kyAE7%P5g8{RUl6h!AX zYyz}e?D2*_F*sA@p9W;6VzxcLwRwRTLMSG7w!o2@mxTkYCSS z$d6L$OP$a_%jaM6wMk1n3YV7@LC>a_gY1JZIPMsXVAwV6u0Q}DxdvDKB0cAAlbm)Z z^xuOay8=C%)5!PY#{Kn7?X7e)u{23fXmzgI`MNr?r#CIgZ+`;<0v$M+s#4wf0i?4x z=Ds$H3_snNSG!a~oyt(|V=`W+^T)%&RLDfn!X(*72i^azw??k3P&J6ede1!G9 zt$PLvx5bW|A=t#(hK}@R7rY`Se+%6@IYZ6ZG*b|XhOC>U>B+XwHixS{tsv`K5CJ;Z zCklbJAR_x+=*zOJP9~Q#r^@G-E6i&o4)qFyvrGNjyH98^JG@{GZ5hX}~op5(ItZPJPfv5NEqrUMl$C*(CY{>sXvm@~WOZ6LhD^rQL>S*`s)OpGAJ zMTtgF1}&WIxvs55ai6ji;*sf^zm9)c$$u=BdRV*;dpDgR(apvlUK=f)O6bz9+N4;k z8F^$|Ld_!94+~@Vv(i#Sl$3fnag1&ugvzi_N+NszrYqmRZWiJZIGYGZUuCtSq|k|$ z(SE$J22E`k{+^B*PKk7*=55H{0jHKZea8R;2!AiH6Pv6~-`BxaAublO?neR>E zwc*DHW8lhuFhTnI+IIPc+W=1e(?)BjJt! z0ZV0Y;md-elfj~7-RWI=MQukn`kaX)m-PONA%)Rg`dCK~c2lcaj8ON@N|27<*bmB+ zel3F^k7ry!NYq1qeP*m#w?J~2OCLdIZ5mK^nRw*oBvp1FGcOb%TmxtZQ#R~ru zHRvcL^I6YH`e39up~K>f&&PO^ANzm3dNkmy_k)C^YnN{0f2b8Yn*5`R<@w0{vy&vN zzs{#`h|!1z{6HD&W)T>_Zp8vpj&$-y&)`zX7|EM$6{69pyZIEZ^68Pa`&cMB~l$6kd@ zB*m?Zt4VYIhM?1rQLQ3J;JKGX=1?ld&!PZUF^N<+TBH4-4mZ9W$6iV(!Z}zZ!xr>Km)3Zyl`Hk7S=RqmbgNI{7zlDOr&?hO*UY2EkLb?Rb=x0hEt& zc9#C4iX~82IYCWkcNSJCr}b?FyHs$7!~Ug3*rM zg1R6XmWHkWCIp}vZrI?g9?yTC?HIiSS-sZ#u=@iImC?%R`7mo2_mQEm<1kQD;o-H? z5t-wMO)-s0L4`*Ugej70M3D#Dw-2ilg@DAv1t}ws^rT7tDqqR$gXbMf%r={4F01Wc z?_?%RQmd%p@mXK11e_Hpl#X>zCtG~#HTYDdz^Wk{ z9q8ZNb349tpHXWKxz;SJcrDLUVrcgMBlvAn{MN2iwiz5ivvi7^SnF0pJ)H~SeQJm2 z1j5=(|M(!DJ|g(XRENU4=27tdCAq}N4d<~7AP}tM(y>vSuX~fE?-(`LxM`?{>jvMe zxK48$Wtv~-n+_X~HZ>Nzt4up4pPhZq?0t{+E6^Fk(Q4~PBXn;l9iIkz!BL^Pk!>p+QabY9c0Y;*rg zbhQ{1jJ;y6xn{ek0<%8$ql;w?*DQ}i=d8wi5$xc3bianZN>zMyZaf1WI*mcuUTCHc z*$GrER=ZgP?^XyBH0y$rY02K%Lu?D;_Phv>=%%CE>Kqo7sE#o7 zv~-?lYosI2v{lxA)(Q?uzix1C$9g}HYxsRrwtE&hbSMrC-w9O|hUjAmG%Jwnl?N&3 zhy<#HE7$QMoXfz}OMky|R=QpuZOxn8`0)7wkT|s&ZTq<-OsuR$y`%5aJ&~AXjej;o zR~p;bb;Wh6cG0t8Qa|pt=nt7W%aj8eOjCR)L7MRGnH{C`T;MpNfdvA-ds`Ha9Fgykfo`T zekqWfKnwYV_LNQRFO058YYc?rkRxI!^8?Zvf5-eP!XJBWAwH8H@8ZzmQ5_i;d4vKX zdzSSqqme|RzX(_O#xyv56Q1GGCr!O#!afaI#fSP6{HY9%iGS#E+v%t%Ws!X2;rF)g z8O%owB7|qvCNsu}!W{N6W)6fnp|w-hgpU?@cP^9wBDI^?Lp_Il`l z!iIm7G+5$qRgRuR9*bL*i}YBV`6wo8f0TUYem>bU{@2on&yV2MYNBVHuz#TZRasF7 zmga~s(+c4r=}t*Hb6P~^5#;&VzMcHctyAAjkNplYH7fS8Yxg0hX_@1YSQP<82B%AQ zoN`80K{K&y5*vh@=-=K~tGB)^tTTq;_a2Su8p(=WF&4yHaKUp9jm*cOvKaM@Mf$emz0&TnZER zzj#)*f9;xA3CaCl@3gfY*_<_GN!_9NTC2wCEam#kiSq#FKfqLr0OCgivVVc9^gecP zVgjism0xZe-idn+gg>$>&6*m|cw0_aq1%R2n)o@bMZoN_mhXxPLea>t z*X)`PNB;ZN*%Uvmk3XK-pB0`1rOigZS1-XX7OFzM=Yf@_Y>i@kL<(eB?m8 z&yJO+`f#UBMG7yl~UEMFJ!w{@@({;!& z4dD`hKdJe%$`?UEM*mJ{tY(B0Xg2u;JGqR96%rO(<}BD$r8ByU;2=Opa2yCCh}*>W zQ0a~1Q^7~TP?Z%>+Z=v(Jz4dj%<>XVfT6a!89$OYwc0}t>P2{)M*o#Z7W(Ir4)(xW ze?48yU-_p^oK=GY8*y1gtk^YBhm0JWNbY6@*T&7A&bVmGID{&c^YQpi9U7m#U7oz^uAA* zI#C?f8Os9bzi95UtvFaEC+(>5zgxu&!7cz*5h9)oSThXNzs{fdP!n(2g+!1C`M6 z{SqIK84yyX)5GJz5zSZs<_8#5(O8w0O0X=(0&!%F$5rD0m3IXp-~jGpHAkF#Rw+EBddU_nv z%*2QJ1@Ce8=mkN6li5)WNhJxA^Q6fjw_U`-B-2d#O62Gef)k_Zd|T+xBb7Ap z8lu0#Sa-qd)*D~kpJ~fm9VY_s;vFv=oBAALUq-cr z_cDgD$og3FD+4r)2OG>#MuJT7T#H3L&OCoOc)b)s-H98Dp8C%z@7iu-kkqN$nrI4O z6YV3$g`vI|((o@v-rYcxB6mW4{%*6b^_EdMcM-R@-(+&np5j6jgACk+Z8!G(my zW`J=!%Vm((6e-O?nRoc-w_~D$H$B(?C`lFg@c0^IFxVxz1iBVQR){(=nw85^XoIVg zjMD_Tuy%uQB`4mxpGa(+Rmfb_MrUP4$EW7>I3y^DRUBr6gHXBQ#=pD1csg`yBk6b& zGwD(1sLdr+JGylxWuO>Be2F0*G!i0_Ugx0n(7kOw5V$F|Ly0qx{)s;>@x5rG$w5~5 zE8$!7>m?H^ShOT=WnoqqcL*IX2Yp8QC;C@HnPg?a|IV6+boQ;jlJ&{t`*NFlxjg8Q zPa^!}wgaY-b>V!I&#+R0R3Xg1f@45i6D;5<<=nf6@ZnBJ)Nkr z3PH*`UUI$V#4r)I#=1O9Or0K6WTXg&q9K52&@uiX%2^pHOmK}QE^;P+tCx6$vmB5+ z$h@K?fQ#dK?1wiV`rm^O=!HO0)Tjwa*|c%E5RSG2lW#I|`DSXp|sek4oGcOmib>nan-J-$Fj4@c@VX^dkBCWSM{!sUw>AtZ&%ew8P7 z8e}>7`Eht_`R(jFatmp#FM$ZmKkVg{tKA$;D#-)Qpoe_T?&n2OrM2SFoa*FY(ha|d zSIK2Y^SLd|ciFH(4*o|GX*+_^1K+7XMmNZuyV%I;)Y_vgsaIiF?}=Y6flRKtXcL;9 z48I-M&UkM${+i3*o74mVpbhSYzZ(v<{{AsI<%wr6NNI?>DUt7!#saKM{QKpRVS+3o z#>)|j(3)edYf)Os!vsEbz@B}toNcb2<#*=zn z$aI8QOK!++7$+^JO~55(OI@gSJ~V<<_U;seR@Zsd8uv$4yb?bEj}o^G9F7i# zVIuY-ERiZDs2Vm9xLUp`|HqwyF1eNouz2I_b8)csELzDcrb;ke)E<`kz;vh3HI zLH+k%+<;`J5a@8wlA@t>RaBK_(mV))_P<7Pc^>vFPFt^sYy?A>`5q~A=}KaPZg6P? z7e*Gz1Bg%)!hn^JD8kr=nCziAob95DkqTaR=>*$`~7y_i?s|UzAI7w>0!67uM=JG!b(CUYRpQI%+qA$PII?e1(m51t!R!AhSmdt z5T+SFnx6DHO!uo7$aI~75-x@GqSd)d>jX!d5lZ{Zg3!(8AJ6vhEpkCvpKJXryL3q% z(X$HrBiC19!+WuvW=guK9058FIuZy?yI4b*q^dU3PIep?k$7wq1i6cog1WP_8OFUW z-e&71?>+&Xx6*SsaIdmDL*pHPrxs%pEOU`p9x^0$dq*XV`Vxuo;hwj1=oV2|15${W zCVdWN20avi(F1OlnU|u)5HJ%fk{f0W3AQ+?w^kWyt#9Rs^CcVFVS^=nbayt3c{U2% ze9!)b#!-Y#{ZI)XPT`^nZi;zY8B>vYb$#ijwaV;RNcuy{6Ww4X;s4Lgh=~e*c3JYR zOvdtIoetouk~dP=zv8{n8RVD#>mhr)z0T-!9>YmRZqL?vy`E)*HeItFJCtpLrVNS} z$oOBAkVh1~q0<`3PMD&)(#3;FNQluA_vtct3aS5w zTy`SED$kkQv-|}MzDZRAB~T$GdZPOo|12X!u2 z5ZnPRylC%*=X8hc1CVa}`>sc*G}ok;J#lWODn9w*P62Z&39Xos5iicrsc824&VJqO zrigc$YjOl512=~#>DA64?8vPt=t=e-(o*;|Z^m@FuQEGSS97ejYoVghlxxMxX0Nkn zF@Lbzm4*3EVj~IFL`RY`B%vaQJjzkSi24<;h10`BGsE53;?-fg?tR!QW2ZNEu-#(8 zR0)3h^siq5MFaod-k0V1o9IMh;Y=0nf}j)d@NG1*<#EYGMvfwO%_x;T@ug>Ay^9uO!2V>9uAXh_dCDn^G>{PWB$@NGxY({Jd3O;?LJ^eb zN!OvPaNmp$MRRME@5`?@(ojZGA@LrKmv(UkR!)YD><@0qjv4}KIBk~;pFeQ?kCugaPADTQ)$2juFElAZlx z>bgk4pTypy*z!}KVg!m9CsO|prf8#%W_|PgsIc&*V{;DslNo>M4}hfZD65CD9o%Sx2qQR$mgBcX!e~Z~!j!E~w|DEGwvD$K_Uf_K z^7Z{3nlCeJ6APZZ=pnJ1#Z)~{HVciU4m{MjuOkcTcM?-X`x<&YEBozj6-nK7#0u2+ z3Mr08Ly@@eo7Hmj_*TQ9CD@{SB;Y?~m(1;+l~S{B&dJD#AVBe+;9|mpWcSwkhn)3)!5RgC6y-Ob(>|hg`^*_Sa3r89FT{Znm4M2Ha=zMH*Fl8J>ZXdU z8}3B|day9!hB2y!zGqr3jAA7na8Cj(zaSl`a+l%3S-W`DuZm^)Lh@QD?Bdf+?Q2#D zK%J${`6^S&;S`4axh1N_!tcj&5~tTrwUNr&;Qn2~{l#B^j77vl+|VSb=m&8Ph?Kj3 zs%HZa?Mx{ClnZ2bHM#3h(O1Gi2$L;C4pICtku0C;va(RfSQF7@TDxTofC)=UkK>Kjb?c4DYDdIYjQ zM1RvUrz#&{*_l#@i8@(*9WUmEi)~!;ReMh&)v|*{ zsE$h7uoq2G6QGhc?mN_qA-i|a{LrP>o?~UgB_ltCXOn(Qk18LnFq&MEW}n07u_VWu z>p!5`JkGy=F3NkJMY~ur?RynwKa+VsiGWc3tBCCSP4*YwyK_E!*Uoxek@PfEM@)vg zLzAh%NfhWVQjE*iH*G>S=U`?3|A7!kAh2xF3b{B`-z9#{WgV$rh@gUoy3B=yKM)p` zk}B>m#DW(S)DcJPORN>m!$s>Kk{XnZV+w`Kbry#pC!sUFOz09+4jm=<~2H_Do#gT{Wa%~zO=I%CS^#6=2$&oCfD(Uigim;BNJ1{O;A*ieE< zcJX2mm`eRYiIoF;t+@AdO9oA1^#A2r1A>Bx{4WIBKEG@#^(M+HCQO5 zGZ`lRfP?V$11%NwfJTERn}jfxW)2gpU-7*~?xu2}BY;Rp{1`G8MJkS1JN}$M1pw`a zq}%#}++@xQ057JVI=RGt4}-QPuk}Muxv00gd=PLiTN-`94eYJ4zKdWvjdq$`{hD|* z?4@6at8`1IB`pW68aw!CD1kHGPZ1Oh8%*JnZQ}f@SZ?sGBRxB%KLZ{)hOEi^Ja2jl zWsL*FX<>H@D#!@s?(LVWXu1J ztN)mjqb86`;&sVpb24{BZW+6oRtcMEL;fEGi0vPzX0FQ>5gNT9$Tges=kYA_=DQT? z4uCeC?bFPT+iF4i965^&QCdg*S%e+AZ5AocO_?wbtJvJ&46#Ded=>BvA5Vv4AF4=@ z?CUXKCdMQUniG|K%m&~{qrsT+91TDa?uQZ{D_S^ZkekKIa2DOk1Q$0o_pKZk{!;Cf z_@Pel9Pp)>se7YFcs~@xLjOhk|L-x031;6oC{X?Bezf>SRMc6Q2tj2!Dj3$FLSjeK zQ8p*T3S5ffI^({^O^I^wQd3H?<2Md86b$2Fejy!3HM9k zte!^v6D-!oZ)Yj`==Y=}igUS=u0fsUz#f8g!hGwn@=gLQOP$v?b+iR<>WyI2Y`1;* zUg!b^g=3X{@H&^cD$dt>%AkS(DC~;_`o&CWc8vVD;#JZKM=CWa*ATgd-zadKRy;pS zFBx$cY1YosNI?!A4RY&v)5UCIAF1P$iHq8&@Fqe;&uNLk+h;L9m*LygCH>09|AP|v zUm%{|;kORI37og6xkcdI+siuE8EXD67-b}?yd`U+ppa$00b>)h-PwImX#PuXAc^>K z=U~#!eUtQ<(fG)R%G_F(+ftrWxGuoHL8fjZ>aCE2=dcR*NMubdOasEsa5EIM3_~_8 z(*JBm0{P|U>ADIT8JLcao=h=aKh$97wc`_IyAk!hs{)K4mb(GCq_$r5%8i_I9=Ye5 zf<^oPK~zK$!D^3->gAncUyZTPkTs41NxW%{VpjEWYKuw>qizvmqGYC4A-YhAkW#L6 zAYWD;Bq)OxuFg#2@H+9shCGiqznYh#^aG;KJ$rUZ?3`4>w?R*PvKg5OjTxSTGt7!8 zaWlE;xHPiexxCZrZ-}=-8k%P_RU7wl_+b=`DV$5B8K+DNfhj49Ngl$qx+80_pr0q+ zxi`eFPMZn;KO_wg0yAA_l^5e!-fV2@M7Hqg6opY_s8{}Q^rBGpoiLET1g|ov|K+@& z0LrzoK#L2UdC%^gwAzA_>#qRqvvb;=gnxRUrM9 zc@V5tT^uentPekY4BoeMfWY|GoRK?bPxib;2N*kxmH{}PYd<&HETlU~bXu0%l9{xU z_}HoPDmXjW&)W{RBGN+zNM0g@(vQEBR;9Df^p8lw z#%n5c7Bl?goCt#b&=b@cM3Nt$I0a6;pA-gAu=96<6L~mn3$F<>5h3&CdCfi9AdwmJ z!Ico97DdeYEV);ftgw{j;Q#s$c>E#{PA9JHcj;lpTK2eb(dyOuL>5m{G?wu-;wlfh zw5ehLb+zhO=W3UU|51Sfy~3zW>IT>St(W0FW!mm!V7-31cKJJ2L0m_oQa!UCX1xD8 zPX9n+ltc`zA{hbw!iUZGqCjt*F9x~*alXq|J)vKn6?XB3=R=!XFpJZ3ZqR(FeH01E zR%p%G7jJcTdaFxDA;b&s8|6?ya0IKh>$Oj`r~6#=bfmI1z|pKN*Z{9yG4Z}bD#?bCxgjm3G@B!0CXOo3NUlT&G^~r*H@25z=Bzb%`FWsCU@X|L?x(@WI&~w`R^RSOuh9Ba(OnuSjFP2s!CCD*y7U zenhi>fR2l%@R+%Ai{mu$IEUp-&Zmi$o|f+Lu7!3Pe7`+Q<)AP$y?be~BdwIJCH&B< z9m7~Z1m$Fu6sF(Y&zqzXt3lgO!>hkFo~$mDhPH1dS7JH}ndJgysp9(JAiU~V|0ocn z!oQ*$WowV{H(RJFSt`;njS4;RQI=Ts2-i$2X6ea;OrNvS;zzN@f2Lm@;HUktjtr$B>IMkclYOAX|%xWI@m#>Jxh5+_773!~D zo?|($qp6vNX4xwd=aTjHg$W+8!H_{4X{yt*t^`1ri@HJ;)$!ixi5g{s{Rs5Nmv>Tp z7mMugq)Y7FAP>j!1g>3mXq0`nrB4~$6a-X~2kniEioq|5bkyZD7jcOXu&Q(2R=>Nk zo_rlJ{Gd((rn7i&r;`6@=9!NX#NjD} zaT&SSgJX!9-MxolZSW%I9Rr6{fnEhIA z2$84FX~oXrTn80B>^4|R)aT062s`1(z0u12Wb-z6qTzpVbQTCuy?E^UHmHUL^Jein zZX&WxBPnty$rnTcrDU8@W8Cd)#WESzsA4V3YL*)yxIpBG`gwUl2+-FL4Q*INQhU)i zIwZHyi)0B}7Q#OY0Ta+ZBd9DQDdI$TD7k5V=^J!f^(!&f#Znc8YXarlp}uC>ff z`}3a$ixaNuaH(oe0}VtOyW4f-nD^|2<}uo)bJfAuA}uzT$G@fD8V{w515!l(LO5R2 zJDV%i@;^P?M5x?moK&4_)>9Vq?j`6)GqLUb~%ksQdl{lle2K zua|;PwNayaP0$H7vc$i~6%EW)jamCXn`yl z66~=%N&J{7gDk^zCAvgsnT>;*?@k;|0we7I!e3;V-{wcD0Q2(?H!=3j;I5sVA$L&~ zLm4hp6yoVm+(rAJ+`FsD81{_fDs;fW3E%_U`W+ynp$aW~WwJU$IT{5QewKz0!5GwN z?fMP$lECN|C9HV;wtj~27Y9@VRqpoiX$l})R|90}V!d|_GP=+07JIYJK8m5rG%-jn z_j*ZTX1>%T%9JDelg&}}XLRgTZrEtGEU9POZdL$y=IM$PQ8m-$FJ~-+5Cr)xb}D)y zDUVUnjhXv{HOBKvdxJ;>S|=03(Zj;mbSkn~t6jG9SID;ik4nOX^~a#xI;iS8h8H`@ z|2o(mmX<~O8bf&+N3!=mWLmKCfd%Vb-mHcqDg5^I-H#AD%oXz@WD8S9!S=U(GDD*m zuS{l)8j&}b_4pvWl#p5oerT(CQ}3M>gYlR#Jgiz@fgDm$quB1G!t|_Xx0CAxVJ7Br zuX=SZ^9f98a0;X_R)u0vW=VaG7q*t zX?+{=p`#M}F62OWScHawRvK8_*Irs*P(7lT&xz|Ydep#&EMK!pg-yL?HBrrD2Annl z`TsyLxu9VAzW42@ubWfNN70LyNt`q|#jjd!sWdbWc~x*#ynUhM$8HKX- zl7(~kNwGF(IkDaazjmMMR>Q2a%ahfb9`l`A-Z-VrQC(WQBgQG80p5%Lv9d!0A$7p5_$Dv>|1)3J#Y z)tIl;){t{or?Dls|083x5&T_BKRhXV?m6?Nr`Yi$Ls5mV3ebQ_){!pa8MMGf9B`y^ zF(U#97CjUpqWW*(e8w(vH~z0$-v9-MXlL|Zqel;bArTUBTW~SsPwA%AL9CRbBvoW6 zZy5cobNN2=3)@aI4c3APP`@@u__@by%0j zTcg@#?7lkkZ`AZWJDL9)XSlQ<67mI4I9{o0{LW91rgTPi?73Dy*m<(v?{t!VYVBi%QA)W4l<7fnf1sA zTBy-?nkEiwru60&6(}Ga;0eMpRl^^VwPT&FAOMrlaK5e;W$c*OC_Y9s_>4!P^edro zjmqHVHcC)R-ahmyct>1(`=sYPY2le z)#lLqS>9#4p9a{IMHIF_BCgD*!$XQ_WyuIUFm9$s1c|iT`Yga1I(dhOIlm0A9N7IY zY~&FG%Un`@`*6MbM)*hasc;91Hit~UY_t)}C1k@vL`#7AxWd8WqEQ4inGm64^k>sM z{3!qKE8+D6>j?-|eD3~PXl!Ksi+LbuVnt5+jv*0W(^4cHKiq@wudeE?SaaKt!}N4Y zwMw-cLZ_U`34tdzX}90zwr=Q6;bZD%)AORTWVm3n{daNb^|-Zoqq|-C7n65#i>6l6 zkbiR|@I20+3@=F;`thzk*@)h)fn$G+&DlGTlDPN%T_PZ@?@9%n63iZoH z{&zEFSP-r=&Od%%^c*nM$LlQyB4?qORzbOOz`4n zh+TNO?48cQz3GiM>X5*1C574KkfL3q4Hi6i+3b1AY8Yq&s#fIr%^jqT}Y1>{&MWSb#@(@5?r7IBfW+ zDV=HxbKi|!yeu7ja3o0!+g~ONKafv2zUnQ;h8YGJS z!>CR9%~>GZXO|@)y-7*Me0D8pt^R~M*uNpMcf%-tUiXwpC*rTXfr-wdY$_4v5yI%m8(s$>4D*x8CZ z1FD0EHR;2V6xWv1wEsgqnj}!SAdm#Wj~4VoMdi@tXLECA(jG&wBXSk^F`96AXH2FP z=!Hd zlI@~Il!n=usldyS(jtimrf}5S#HhOzN0_Siml7o>0c1+@@g2#nr+xRtNjtf7O3#kM z-}yWDGsXhy2xsu?1X4Kgc9293v^322z}GNN%mdoB6WYy$Fwe424}Nhf{D$kdzYm%< zl;fut0L1{}gZCSBDerhbJW6^@2?A+KkbaXtaz zC^Xqy=Nc5+<57ZBc}akF0hdT=0w2#gzL=T&WnISR{)QuXf!{)4)s<_$m3S7*byv{Jz&4hj z{hnC1-|Yy)5CI#u2bCXEB#8|REq6c473oK`d=A4_*M4XwJcf7j6F{x12Jfce7%NQ~ zpp&A^DvOZb<|HW@HukHm5G(lI=>PL-8GQz>I!&S9jq(K;%OM8t2FlC!wy_2jjW~hxW{0W!$O+lYvt8qpo4=3Z-_XcDm(c1)mO^07(jSSQ6BZ0SQv5jN zo4#`JRmXYcg{PAwz(^Y=D+@y+U{iP$G38A#bD>n>1We&jSO#7Lu|OuO7PRc7?BrQ@ zeGRjc*>;feOp)7x%3SN?#~LY?$SaQmsUrje_eCCMK@;2IFtTOf;9ZUj;Ww*>f+MBw z1z3U}8y#1U^KMr@hyt$;1jrdJRV+-c%q^1^TiLu1e(-cAuCDnau2 z>Rq$RcYGLm5F(m?bP$q=T#6EpGu2>c>1|fk`(}j5AnxYh#KFiKIJ+VEsI&flh@#94 zb6*mS109i*5Bs`Elqd-JlRD1~<-3K1sS20EPxEAg$QVpOWG5d|tHc4P;;ddsu{b_J zMkVU92DKpdRRzYV6f8Y>JV=qIc9ez^P z4MnVcEqZn57gNWhYWgB}R_*n{o3>qRO6#%X@G`%#<0oc)T#{${l2e7df@9+%fou8J zJ3~^fA$-86g*d80>nB(A(yG}heV6+Y=g!w1vzDhHB=~ZXAoS!6&V9)Oo(~p?#ZY&g%?FgVWWrv;`}b@dt`zx zV)MA6@RrY?Er~zKOHLC56JJ^A}{Qk;I#)t6^U=NgC4%6WSV7mPYDW38Vv?*U92GZB)H+kzD54j^IN z{7!YPPT;0CH!U2piFP`9SKaPhRMODI%f4oPku(*|+i2g_JKk|ru`BgN_;u6u+v(%O zAgU!)ItThF@%@4hClU0d;1gwJe7TEr)8lUia9Ohuef7#9{%%Afc{8>5+frC=;68sL(K zyvSnXUP@$$%k5F>oBn}{Y9j#zZ~Ybf=G3t^NMB$#G1oR&+5%DXQp3rNvdMRmL~w=y zaL6Llq>Wmq&W{N75G=A`f@au6yyqFisE$4&&!K#376Ve#uL4o6kMf#QhEKG2j{!a! z-sb_i$=Y|z2@zt{ifK3MH=A8bQVQR}$amICsRO<&{rtY3>vLuCe&{X0ftsCmDPF+%bW(UPN6PdjQSosh2r}q*g+IbUa)F8LYA} zyfLC+XEY~viDA&%+RgesneM-BiI|W;6)CT>Lr2~T55-MI8!n4Z?bWTi12GvfR6qoC zYhYduxJW*aLbrg}p&D`6lMAs*SIwK*inRyrpX)qci7L-)P5dV@^4jyP zZgnrMZm77-|J+VH<`Kug|ALcj#P*n`Cu&!wmvyJrfP4A0#eIY@z}rsn0TKDQMOIsRBgq8~3ohg;b8bEYDfPe*o{pZDwW$iixgU~X1*?`euX?_M0h zWD}-r`5wBUaC}@;EpS#D(#BB%1Zlnko1; znp+t?h9mI1NrE~p2kEZyw2f$7sdIqwM3nj3rbl|wQgaqvTHMCp_Q%FW;&O?Y)Q_c- ztwB)gaOdXm3CHRu%n0dJD54hpwn`4%gi#S03<`9oka87&o6B`l?thP1BLsxaR7|(Y zeb?=PIb@WkFHlGYFIt%64hVh0p1F3H`n%(X{$kz3kzLd9k7Szv<^YoYs)&31EO%A< zw^kvS{+GOOLO&ISvc|t@v6K;0fE81)_+A$}Q^bj|=20<)8wX3?7F2F3y3;8dUz6Sp zSNC*|WpAlX(NFoli0vKJXlAiTxmOjJccG-``F%!9F1Gnq$PT0JoU}L}aU$DL{c=-#;@*x1+!Dhzn6;55zkL+XCDW>J0gJ>3-ff<%foXjOKdYSDy~>|1B6zfwSI!l)NUS-b>o= z=#THOAu=(Q<|c(}c9qlp(kkfZm}6cyArC?)@D@fn*G{2KZf|Nu>mZT+7y>)K^+A|1 z-IN46De;w-=1RBqxzv1L%IKE3BiNXiNisU6cA!0bndEUebQrfnjJ+l4Z_-W!Oc5tL zh-+Y4eDKug8?XZ{q~Ogsr#mFEP~ajq0rpqSX+P~2l_;^ki^$vwnP#}%x-hA%srt{2 z-gCTk--$707e)zerIB?CCXtLDt-9x`ihp%=s>e(j*yd{`aTVl0(VuBt;r}>7mfU0M z=oULwz1*(5L@@QglV*bU0SDISyk)5hwS~uhG>of`i=x&V_k>{*SsC%``fXcjctv?yK{9J|v4vp)N zsCu2GvIpTw8SUd|@APl^1_Gm1q%LM|bDs0`2adPUq|m=!p#(j$h`1ZiV}-mrU+1iY z*Oz#p>dxV+Kdcd1&lCgEdFoxR-gM%wSN-WaR7b16T!*y9WxPXH@f~kfDUjXFH7@JB z8C)s{+-*-@(ZjFnBmie@z~70awRc$85h7qPuewEqHw$x%t*!nWHjhxSaQHxGn3}B>>lzql|q5Yntkg>IzOo}f+39iKP zO>zp5b!4+SwD0e9vcDw9kh0ig`GhvSwQM;Y(}oYI?3#Mt&Bi)4Qd{(dsI3BDBk-AC z7Hc18IZPTD$u9qg)>w@ZD!U*pYzB1tTHR*duA}qqF07wx~uG((=8t_&M8ZzwPshuIp2u zZ5p4ikNHO&zR9J(Oc{}!MZq&d5~JRL>AJYP4b75hXupoL>5752Fl-8*fex$}I4(x# zxm|;B-2?r=2HzdKz?ZE2f z9)Cz{GegMDW|5fr7|k@XX1uHh(p0_*3(A%#B?8dx?0nAsKC0vYG_$o|EihmW!n%?oWXU|dR-{(g2N+C@#C755RA)%VWNpGjOE8fo~QcoS*9^bcHXyGiIod}Q;YkA>mkVS?ero@v* zX9x`%^+`)2B{Hw^tDzi9Jh%xGPTr;a_#7OYI-AEoYjBeSQY*8%sP;}RcilFBQ`~-^ z)maS?txPSgm6=ezKsrrJzIqPpTfNr>;h*;rt2)s6y6?*i`Y&URHDt_sRaA_Yzp)2wO;iTl~KO!B>8f53pD-^}7Y?n%P z`}w1@H}A>MdQ+e~zAR$*zX=&+{vM~yjriD)vJSWM(`e)bm7~b8|j(>25e!3D{B)Q21sZCKW%1N-oBCGFw_kh*JzAgp-W3%hj%c;W zV|{QcF^f=kYCS9P^u3?)+-s-hHvW{c;!w}(&fe|1+t}|z_hRY0kiY0KPIv}gJSDXT zoHMW3n0271Iu}o$%S8gLpPdE;L7?Q{dmi38((OIil&Lmj{&OeOA;8l%T4%JM z3N`WG6xVUB<$RM|hlXPnY)eOfEQSjI+Au>R5OS#Y+2^sDk`>fcHUHFJcha%@{o+JO zXzIkzW=&S)`ZzGZ*(p~-PLHdVruoUZeUWO z=L5Ry5P`5wsgl}(hjjgxctumvaouRWm2vkG+I*6Vn~x2k8OF!v2;wpttYv!BAm?8;7E z<`Y0G(8dJ$QvKklJaA%QC&ZMMBl;@q>Q25|)2>tTvA zdamu7Zj$pB)s$l#E5A^09y9j5j_ZAlIi0P?&pw?iQC3^~)-YR`);pyyLe)i`&BG6( zsK|+dpz&Sndi@`ytS~fL{z{ls+b?hdE7U@3kKs)E2)DOYCF(8R`_oRhvX*9c6h>b# z)kCUAZ{lZNpp=qCU$zKttyvR`LjFl;t{m*bV-tA;UKQ)Q1Epv>f zwO64yzVWuyl;(Nu59VgO_c0aBj3+Axv9QMW)WPWXd~-FD?>_8H-S`ok^c^1NhbnWG zVP^C1%Aog|N|z~mJ|Nof`u{6lg%QY<{CD;9O6E=tQkNGJ!yc6^NcB+f33HY**#TJb z){#j$qI@`fIA$KNDxCbu`^u~f1Aryy54;O9@+sV`h*B_>^3$@1F|gB*S7e!o9_!fQ z_Yxs7u*!Bsc!|W7VrZ00197~F+7*1oN)H+sYv>{)a#_2*oQU$pS*7$nH*x7KQ)FfD zUpdY?{?k3>)g?V0N$0v}ey8>|0g?CiyyYs}BGr(}DZ`*iOmPJ~1AIi%GUSI~0Ft^Q z?5XHJJxI}by3v#Ok&IuDEjcBuiaq;ay3L1D=sF%BPBRCDK5ti^#Qs^Ii!Ynce$Ts( zd+hGRbCe*(1mV=}5wVuMv`TG&J|*v5#|%U7#ptDv2KK6?u0}ctLZMjOCCHY=bE5J2 zD*gBhdpW==xw3X~Vx${4fJ(9cDgk|M5P;cYmrXYc;zlcZ8W5Ie(EZD%rxYRSI!Wd# z?qGTp;Tfyf6=}`P=8ud@r9g!?xy=_1oFx`cJM(yAyJRZ(kJ zNfr7zv%UQL>b36O5+?VlS#4#3?huEL6Jf1?FGVsa3}6b3w1A@^L;L0wDNtdGua`WC zvI#Ry0fB~^sR?}QiGeruxR227S!*8ARNU(D_nyeUG(oG=!wKo(l|=>y!ygv(?d{st zGZsw13hg;QC=d+V|Wwr#$F8g34%_)MYtRWn9k^>6hC>VnHraUW?9Vo%it2A ze8L-YN6gub#C~G{F2g{H(N0P)v|aGoZiLuv!Tr6%a8hl^euL0d1k)B&4XsyK<&L2Y zaU#c_{wv^pLIz=?+^~k7ki!@sa%Lp-dt}|;)qeR~6+c%Ab*FXG|ASGnV}nZDMVcz_ z>j~HUA4w$l$>Jtam)gmmLlOqia*7z8vraPusjY2zJAum-YIMV3Ff*}Yxr7@B+7n}E ze$VzcQ?~0mRn1DROIKdR9575TF<%@^E4Alf+~_ylHYC9d;wrag`Yce)Fr|lzY0nHp z;5xw7O_sC5Z*IBNGTS*cyZ%gS3Ei%taLDtW&H}skn@i@KA2xHh?(bB!qNL$*o9!b} zR@DiQy`b(=B!98)J(GacXE@RXCO=im5{G!}ezX)E-ItU$9tRj!O7&d#LppBx=Usfu zYA^rwLNFIQVgBXLu1A5ZOB+7$V{0n^}S5e{`w!Xk@BQt@glw+~#{rQ3O^|4$y zv#%lG7tzbTr8_q}>{+*t+nkgtz2P&<4qowB%U<}wQ~_C~h|e@Mc^+}Z`Co1@Lo!Jc zhX&zgfG5S~%FC7g(-x_lW%hLI9~Uc<4_)4Rm#%R*h#y=`33$0X;}43g10H zz|OmV$Hh5pt6T)As^_(|sQ5RdaM%_~%UyhuT?@Y7z_v7BMooUYYWkwESC$A#`rWjP zHSf*y_-^BZXhN?iWtUURi4JQwu-~<(I^=b zVekG(Bdsf2nh|${98-RT!1aevs^KtcqJEju&VdYlg#~C%t($qHLi;#g z{CViUu=PIW=$TXP;V!DH5`67C-6Hl5`M5fLP$z!9<|&)USZh-Tc6bq>3o<@VMO>+& zBx+-u>W0+7`A*BSriDPpF)!d8bEZT^qeoqFpnsNR9flg(7ZTD>*nC_J(VTzYSuML8 z|D>uKpuZSy+HSommR}@$2BFjA7D z_irfR9Vw^PX(vm0uj#b6>E6|<{E?!94uKZ}>7Fph+ieLpg9KR(#XZGaF*aj;Me&xc7dL8$RUork(!*c;;1D&qk& zG&8F>$D?vNl-`j}==2Ar-KXnN z78@2t&oBGq>R8Yy&R(`?Utsh{HmtKJffuq`fplddu%4K_KGd?>vT zcP}C~Yk=6AjaVFxWTj1$5gWn@^`_Kzw_}g2ri1^u$f@-;(;1_NA%_ZW-oDtBt&v0M zZ?q$sO5Su81PJ&ZF~OeXPFRu$4wGSH43UAg%?D7^R9AMZ-v0P6ZTXnswEfoAZ~1*A z*N(Hd5Qp)=t*rh#ecu(`wNRAsYp7a|>u1XL=ml5y5(zXO z)Q>7pZw6*wOH%}379phhLJ{dTsGfZt_CAmpu_C7^Vuj$kB+&`w+P*3^Ud65yPw0>| zViG5*lVTHPUX+qKo^nmo3V66$O00wa8Mp5S)c+){zud+c+e19!J}gdj9r6b-68EMLBF zl^H479-gri8lo1dI8jfKEv=~XR3@=tn56#~qfm%+JvzAnnM3YMCFW z1`}fG@!!DlLUwcF1u%r~m)J5VLq%xnCQb~?KJu@TLth#%YdV)`#`-s%#{yq^*u2zP zQ|-1YHJ((@ciWX2-b3JrP%|t-T<+g~me$`U*%ab1qqIaBa+s2)kPmHqx zL2$YX@d-1>_UgdSQ{?_!8=7d;q&!f#CYd;6bOjUs+KxHO>SvR>q%9CItBMq_>>G-pKk<#KXkMOqOvA1l9muNDU$9$c9WT3D!U!BV{GhFU@JAVx@vk zZ23Qt3#4O>(Qr(+jedV(Z@OHu^a=Ax5Hynb^txw8xyh~miI~u6dd%;r4OMsi3slB` z+Wtum!G9cC;cO+{GS$2{@O0l=o3qSM6-0$;-V}J(-A?FV>E?wt8hToB%V6X^yUf<4 z+s~4qrOb& z(~lR6+H+a#^{l9Hh9`?82px&F{MpDOhAlxJ5s1+rG?gX{2js+&kp0l*WQk?)Cp;4f z*6Zh#56+kV-riR{LR#(NO*^^$e0fzsNbjXle)C<_%X?)| z%h9L})XZiz${`3!m)xDV+ake6Z_=0dNshzpOfg}&yr{-7fME}nPF4Nu#RAG@^P7Ob zx?hWyZ|ooDM+IyXwS#kvIJ_=!o@bB5p)9e6`speJfsv78OllHA4awrqkPG7kjKF1LbXi9%OE{3*NLI+ z$rdKi94c$?1>FFLjS!S#)zcoifl~+dlR=eF0?VpGI*JQDUJ3=z6B*%s)%(-|FQ^-l zs-bHn9q~0Scj4B|7 z=$Ma8Mdn3=m&?rVyMNtw3yn}M$N4W)7cVeyyZMs@dJWNc0lp+{GVx%2GiQlN13v7k zB$+t$2`3ybwMaZ%yA(6FukF`4ttYoCHd}mo zT9sZf|2oN&Y&Jyj_m*~@z$a_>=8T=|bur2yUKcioiwYW12@<+UOqe{8Mm7zmU?+jO zYS_Ozi{INC<=gc%PY-MZR5bx}?N#6pic^P4f$AekJ(iT1NdAJ=sRnnKBW3S#eE2Jc z&*xrhr>|4w-#bd^(|mhzyY(}CX*!W|VsKXlah0k)TXSW!xgomYlemdmpVb-Q#a+K# z_F^l}6d5*N;h9e;hzo1wD)67U{rV$QwEfWIGqS^vruHIgV5|rbL#FOK0D~kTs=NZ3 zdH}BE*#@KMXzD-g>E-g+3fw&MRB%ZD5iy_XA<%xU{~>`Iv^j8|24dC0i{hdZw{@`ua{3b zRt3RO5cUQnFarnJX0)S&p|K+MU^u>%#svjBlE3%T9*OHS8%4eX&(ASE^)KD2__J|KB2uZ4}wms1Pb)d>gUgdWQX{Z>I4 z6$$kcvp?{}tgkpc=&N}WcxN#AqOzgH`g09hdms^4-Asc~St~5h8t%@gR0ztrl*d^H z-qi1ryuO{&CfJPAN?8hVi-Wghg=szctffOXt>J)+G!mM! z*b)*lDj8l%7`x)4 z2*4CVUsy&*NtOCP8Q%*&vpjU~nbC@-ANFR2?mD9wB&4{LLQB^SK6&wD=o0BAxpeIzKlz}G6DX=y&v`|D137H2t^jF0&y-cQ}7uDzit zxpKHuto-j|ERDm$B3r~cvZYN;u%P{On=HNcC&LL4VK|Op%jP zXCeP#j(;#!yz zoSSMo;O#wow2JFHxMjfC^F98{98O3LT%-wWQ359hq#pyo@x%N6G_2Zm)NiEZE zv+i%fRTt4MNN9LCkI6HDC{ILg`inEema=V?9t0sGvJN}*KLnb~i^qQ}%;f&@ZD@>L z?H%8?T958u(}Z*!koayGa(Vr@(=W;cWKOm4^_6T6+F{o-P}+>I18jV7bzH-0ceEqD zQ-rWqZ0S$vshaz&SoD7SWfi<;pfo|hSx=rGc|=6mSvigsc}`j|UH!_sna&lB2UXIH zB~!m}fn+29>?dtIF2D`t;6qXpCZr4gvBAymif4jQ!z6HHCei$oV!;b=Cjht{Kz+<0 z!{9w|X@=D!Q%eApY3w4UA@M;}1Y)BrA)MKI`RaB-f>Y^Jy)0A+j5)L95Jk&omvOr< z7`E8#NXCSfBxumb=N*O8{lcOW;iM67o;1l*K(0s-cChU(mMMb+hxGiS5aP@EGLS`= z9LI+TzNzy!EK23;mPPIDZGP)K$qkm0qMBBQ!!7|T1Cc2nKw*)jxg6)9068?_1>C>7 z&3_&L>&bN2e#@dp!~cjG>@eUh$MZF_vRqt zA$F3Wy5roF1u>%;sCCfjZb=Dr%{<4S_&uM0+U_d0_ooYZnxKc_U*y)72Bc|(ilhej z5M#CQ@EA?nNT4%FG+?U-(*X|%U;3Q;(I0VxIiNa%ErHTwWNax*NikC17eO=JEbwxN zsc-=U;yi$QIRB$D$RCJ38NM(>resWJ#KTr#8;C!_n;5bw>(3J5Nhs(^uuwJN3DhG8 ziAYV#pI#(28@{jHpHDz>N1%II5nI!!eUApOn7CV1-)hp?@uD+S(k$+!pNJy&_OYocwYtlIxszTgNmK zgpES1{XON|Z7pL#q(56JWJW!h$ic{|Opviepn^%ZdUDldC<xz-As~M?YC)@qo+DA}7XRq-36?QjF|ZAtP%Sbww!oXRCD}o7GRqR=WC>w= z5#w}0yd-F9-|nT3<;io+F2&cPled(v&*?DeP$q?)AuA;PUYWD%N}QzanxIub18N`W zD$um;di^W)xSxuSm1`fqubkH95%9fOxO{XuwtGI^kKba#6xP^ie$&!=CAyNnXd9c9^GivH3J@ zbuxy`)0PnA>Zqm2N$M}9(LtDQVQIXri?hfzCiZ!ZZ!WN600gH zF#-M{i?g#`^=AbY?Rw+1H~Cw!L0k({1dj%jDTlO0%OyttMt`Vy|L)#&MQR&Woc(6$ z%h|h1Yf>0CCQi}G!pu3;h=*>IoggiHD~3n=mzN+%Qg2DsuW32KP*!?v0L41@t<@)T zxaYQDWV8FT;Me(fj}*=K2$s@tq)8V$IZ$S}^*5$;-(SBbVMe{~uCQz)kUlC$lJK); zd?dKR)9w`kAUOU4Hb}c;#XV9+MMZ*j3>k1Ltp&JOE-Xm`4E^KDpsJYpSk&q9C$UR2 z|LD6{7;UiBG`mCd27H=O-t2Sa|Bo^kCn9X$y8B`?)X%0fGNBZCU1Lkv!Zt{ujGIuuP!Gh?KV0z)e`H;M7I z@bL#kd-0jE8_tcldJCOO>z|mAjy)iO12(3TyjiNdPOWaI+oB)E`retMC1E#VNDqP> zctKVoC_2?l^Sj03AfW@u$*pRw)b!J-_G!KTf*sh|-tf`8L+^6dn{~KGwpQ8#Dm|_f zd0-7R3Jyc(@h%cJ?&~mvtUbN_x8^Ri&Ia6ddi#H0Wvt*pyvLW6yDMi?a5oW-Ihbg1 zv&}eBU{qzO*u64Bl*VE-x&(ARNUs9Ep_PgGRU+i;aIjsnaUiTp4ggr5gER6scC7rqgu_r&v`FyZ!34GN2C*~RU1=A(sTQS_epb6yzMqQ%bf!MUj`_WxG+*q ziUKPv2_z*54vt9Zs_lC8py0dPUw6-tX=sd2PhgRweFK|(EDwYKAOi+*sM z!O7;bYnK?S9#fOyUsGt`N!6l|H-x1@7dQv=b0Ov=QJoX351g4=$EV|5%;sn3{{-7! z0#HByKkHmBT1undX!C0$`QgU{IG6vbzrQE;8QTcMQfo9l0{`13`GM592x{b~S8>wM zTqG}wL~_$6wZMKR7BxYn42CQPp4&50?tb znO&FK{A+Q4K=qG@upe-%tI!t0538585{e#U6N;>fsFLsQK1WKx$G^)E@fTTwNASop z;H6+-emM|zN<{IOzlQvHqUw4HpU5hb-C5V98M*)>-H6I6<-?xH3V?pqI}w7HIyKZy=IzXlgN$lXR^_V+ zDMiwb%Ux6gETc`jIVGI-N#jI()o{ePNJ!)1)v>@~KMx^7sH@(8;U@v$XwK`{>#SE# zycOEP9%k6^R2sH2y;|vVO(&LH_jm>-TiK>B;U3FGt}!- zAD#I0CStITX!gb~m@GDOXyCBhg41{?#UV-R^B8?bB$cCoN;QA&z3|4TAxm9>%g{9n zmWI6+*}55p4OpoT*hpY3A;2^LW|CykOM>?!BrW}JLSaDkxx*8bY`1!@y4y{Oc^%Kd z%vG+KmrB#0)l`>(0eBfpiZDrH-!&!)`pM*==YZ!|Wr3jzrUk)N0j2vr< zZ~!rsTh#xg>S(Y|`4%qAVAZ9lpM&L)Swf_ier@JmozD~!7Pbz((;bm3;HuwOeYm-`Mtk$2Bd{{jZG{CkDFi*TP4UnmsMaKWn>K zS&0VdhjIhcD`kr72q0sQh`Xuw^C%X9TsDcC&22JhRSeg(<~mB%WUp+)j{rOP>1-a3 zLK?J;N9oavbOLZBTWCTh;M8s>3h<|0GJb55(Ea!0Q~NxxyW|#2hX_7|G)+N*$7ANG zua9ZdU3rmmN28!Z*W~;9D%Q&o2UD-xbOcg**dHTxI=_Le#%F)sTY26&b^!Z_bftBE zayS7p!~pG|DJiop+-V@@pJ?>Ss+4S~cOk>8i&t4M0}=?W8FB<0MI7a1_j&f8J~pxi zo-Ys;DO3M$bg^(Rf&ZcIyqIG5jt4LsJ05isMr1e$2R>iYE=Uhoix)bcf0C1yJwFuR zcRWNM+zytbzp;TEK=Qqfxgon$-1%no$^{GkX`>lH^GHSaP4Y&T*r4kBBQDJsc76+l zjy`JtcSw>`Cu9Bf`iT|l^RKj>mAyiJJjPLp;V~|V$wTN0i@49JBXx$^V}>2vKFK0O8|?w;I#`oay33dvX1LL)+{Q-ZU}>^M^_m&V@K}Cq}bSV_My_N>L1BB~N|6 z36v!GWG;#nO-gO~=}_D)r#3TcYbPn@)exks)g=S&%FUS2LYftd7ShE-#I%pXCCLl6 zj==dpUFOYg*AVrn>BAcTvSU==<~)La`w;TE1h>*w&wcB$U0HDKS)dm~6^BYnUPZ83 z1k%@0+AJ!@DgUvKMe>Qs!jXSuQ2zd5#h@i-Hy4RE7g;(ACYEXJ-R1HkV7_t}u-qL> zGTqDkaOUFRg_YBGp3}7ae(p14@S=VB(pebY&`0SZPO|NWjDdA2vp*=Ls0PQc zs(tvfW1#L*BY3_2D1*k$3mT#-b=-g19Mn53a~{(4MFKxSd~jty*h1q=Yy8$;lrff@ zoeQ}V*up4=UY``#pu_;(IEXcpO(nI%+LHTZ^Pgz|;Ap=X!PR+PS~|`YcZ?nkaem;1 zvHcXb!(I`v4O-cI@v7g?vqhhuPn0HQb_ zo0kbf5!{lnAsU`&F+3je99`~S9nK^}?s#P{ckC5r1avgxc6;mEp5P)ueSLg<;Y%LR zfzH@8e|5p8N-_{YWT!kyHA`c&Kgy0Z*^)qf|0`|O5cq%d4#E_K zkqmB<#&1gWv1l=n0m^nmgsFqX`d|^}7n^mHlH8m6UA7uA#$iehw7< z`HkUG8yV_-6!c(a#aoV7vkzf2^&!J?hU~K^2D@(Nl1GrAIb=8^=3ae#-tEC?1%FKy z!;PdbUF0Ci6LNZdzL<{x{(p0w5_>n{N|%_t<=gK`_wOLmtE#l%okbw*3X72Y-{d^w zP}HvD{^0_|1vA{oT4DT<+YQU$CWNbRJBDl+Z)M?35ifv*QmqG#fJhV`0jzqWh$m4S zChV~U8D9%#K85vvp_>41P!tV&$S!RN-na>LxpB{Uy_wk^LHcApi=Kbwr!)0f8WkVt zfRFIN#`=>pWAbZ5#ML^QjF$ zZIbW{XxyEhkm|iB7eqycfDr9SlsFJYH2`Fhpvs8mH|Zdtn+xUemH)MZ|HX0#G``{Q zHwysuCO4Nlu-Fg z<{tCoHwn0`Zt1Dzlq7GaDE+Vsb;YWkI3_2WRzK7tl-ZCf#aCXXNRNQ$3gF$BIjH7{ z=inrb{V_@Q!49^<1E3cm&$qb^J+MIiejAJ2aZ8-UB4}CKdb#x|mHbo4(72+8=a zDH9Y5Cs&A9SwUWG|CTtY=?V>^Hodh(G{`<3AzfAc9dY<5`%vH5Y6pUB|6R^1A@5k? zKO6sDS1k#k^xcK4Lu|&!T89V8-%#1YC!&KUG6LBSKuSRtrnrlqV=Ym34SV`UEERCW z#7sTOEHQ`D9FIO*H%1?k7=t3IB<{{8xSLa&zwfdaNWq*38036sl*2qW(!u*~=q260 zPrPyQ9Tuc0HOTY)6SO>8_V_)8>>Z{GYQO(D-98=)QC9CPHqkWNfhuxZkslxRX-$(g zr_@Nk=$Y0om)XWLzVzwF6g@xD(~k4?Gd^678l$1If}+PRg9gz2fcVVy1#0M|M5=C z<~VqSuLqzN`AfQSEtVylseAPE?nzN8S13tUpXZat3Hy<`MG)-kHUP9e7gejD7y2&4Xs?w8r zEK;o@y`P8XTV9NIjTos|7|8`|$lE>~v`T;SgI~MPxV|xnQ#QMmusn>pfc^LV;D!fx z+@fcSjLvq|zav=ykAVY3!&7d#B9gM8$L@ZgKes4!nDis4XL61G`K783p6+xlg-%)l(!;3Zo$T1~@o4RbhGWdsgv0 z%Q123dlco@+*BaMKM&7Y9EC<4W+*3aVl~JpKK(lsHHupDZdxilw)^`F(=Z@8;+y5gM=+SV zQJkS2j9lL>@fLh=ctsV(*R^?{9vKy_KO@!L#Tg{a?O*Utleu4=2Dt?N zpZ(uq>sZJ^>exa%6**0^i_AxeJxrSlQE^smo1Gwe(6JPoa#UphXQvA6sT?7pqegLy zIk^mLbo;O!81kbmcHuvK$!`wKWX@5qXjjY$pGkg)1$yG#mGLVh>tTyNj-U9`Qgw%_ z8hURAZFNk~Kd--ZlCzcRQYXmEy^nQciTge>Vc8pE1mnp~k&{#WtO5pvt(qHWql1SP z7D;98S*zs8zXg?_+ZpKRbNxi+eErG<%8H(D%r8C2o!o2wj3P*!JC|hF2N((Ktcs4g zmjX{5_=y<4S`Iohh+sq?Zaz_YwKzN;I-@at<=kvC%3zQ9Bi~uJ|B)eeG!cN z?@u_Q1TR{S!=C>CnEL9dDBtI8SXL?NljRoL>eh+>5z`4yE~;*x)!9Qo25${ z>6Cic&sTrvJ!k)fbDrn9=bpK)nQLa;FJ!IkB@r3bNWz=nHe{SWru*B?JZ@K_#PTvU zztz@sRDg_kKf6z~16y?H8*b_iZLx&Mr>Fr!-fmuK8riN`Yd_fO@bT~c;!$C?B43rF=TMGLFTm(Pb?TT>UmosqM@ zl#Z+mb2zGL*vzR}Svg`}5tiRqz$Q^xv4rgw%a~qc?!ONw{g{ns29VU6lAt1fDR)Aw zf|8AHLlZ0Ne_Z|TTvRHWV;o6?sc#f-E$-Xlr0;q$Rop?;N4KwVSoXiLtHU#PlACz3lRGU<}I=d2kxmvPJ)mKxneNqQ;<}%Im0V(Rr{RHN`IG|1@}}d zmAvZ&1C{*Xstf7iqS(`j{kyY!iUNxyj(9C%y$jzMhEkj4pW(iV1M^NLsA*)IWDvvi zBT!~Yhn*EgI&@q0=8>ePi#S==KOMJRjcEVHP-1S#M&DJ-^De5dJPpp~YT(W|IGVJP zc^P;8W0By8Ifs&XUuaX%NP!bcI5o+5 zae80ttn?zr86Mj**)>9QU~Oa-!&~*_VR`!G7iRyrr(xCvQ}$I+VK%a|g8FTFNM8f3 zl!(*M*N2f}Aq}$v4cw=z21SH+S?r$IJ_LUP5g;(fH3TA8=sY@m$ z9g!h5Xe_PdEl!ptlV=*PMPmyVn39Z$k~26q)rgaH^WxoTNP|V$nfCoRpTT9%-T&_t zm({bc#ty>iNyD)VYs|4M#c$|?%SPXWsHh}+dpzkX-_0*R%&+7?H*@^wx)|vz5t66S zSXjG7%fA6QCp9L=i0plj;ksccM*~plEQdn3;$b4uCn)OOB68UxAAJp4nIWdCByTCe zdz#M9rDX*MepKy}_IlGb&kLY~uHX(KYl4O2Rpx&8Rp)F78d@#E9f5(-fv_VTfDco) z67@Huy&tuf_fePBfo>SDVvYvW2Zu@p0Vs3G6 zaL89G!U-6hk!nL~J5-dG#GTsj@Fhnsagl3Q&q?P{GvZ>+Jc9e+04Z5>g8?ieTaC zHt)k3IWU$5$9(eLI($5Y1gV)a9H;O5X_l}b1l>@MD}ibCal?LJSla*&rXrWrCD=eD zP+mGOCgmD!2vvb%l~D^F3tRQ|6C|@L132?5^l$xV9WXk|bRJei^6$5V229sz9Jv34 zBdOrELnQx%VPSjHl4~0D-b!xSy2}qZJOfnBzrMrPFL6I5q@8h!^h?#ac!yEYDFI7c zw@)`ly&6P5wMyKZcW3`yKS|*W__RP<&HhT%jOJ|U4#Sn5notlcRc90>Y;iPyJ-)wE z?)rJ}r{1%0=@{3Jp~*Z2a*~1xPRPl>Yv82 zk7j9nbCVDo27Xyy3PvkN27bV~vl3T$Rh!W8Wm9Dhg!|a{ACLG;cD?|{LNL&m@Nk0H zR*Iu6B1$PjGpup2LL;gRyTLN1o@QBD9C!xELChWHI z2ogAq7~rBN*Q^;16yr}D&w5+O6w!fiTsDC=|h2%<8oz)7ik|CR@k0I zyK=q^35Kt|O$#>1>J7TxzNhVOYl6^8xE`YEE{(&hKW7OavUdE+KlJX?==tXfm0+D^ z!Zv2b`n~T6)^_asodc>C3_tngHb=E=cp1k;A{D~jp&UNS8;1EtPo0PcbbMqY52-78 zK9WB5M&p0)?ZjKaaiC9;dAJL50+pQ~F=iZQ*v^Zo#8!}JlMI-lAv0s?2ur^gTH=E; z&2h9XKFEYIbUP^BRY_mHoOp36-*~^{U)|Y+ZTx7t#YXJ5IK?c|lg8ciG_kAKGc?S6p__&?Vjw8k3Hc31pt~ZW{>dCepzeKCEQi&4F_-LYq z>Cn7LUWg^)rY(9aR1MrCpf(cXqs#+K_(cmc*24is3L5(`>k|4vA=Pbvu)0=1OBL*#=u>KGQNyNy^#JjG!1mavfenU!rAQo zA5GIujEIn<`2WyHE;EqnyRVC+hLq+o&}xhcd-ebe@r8<>3!N*|SErnW;46jjhF4{S z;)8E|`cO>2chY8Ge{^0N{+t8BCJ|G9Hs`ms5oL}5=m!jpzoYYS!~)wg9_XtL9lcg@ zFCvr=V(Qj{Mo3OM| zR|Ef!yWwm#%F&jQO4qqrt>ZHcTgMB>J;#a>!1gm90i4nA+JIy#Y@(l|3_qnJwGavp z(ka2sGg-ZTxO&i6`}JJrN7yG|XV<8xc=PC4=A(EoZ4~qG*gXKBwuqmg`(Df0HGVH7 z{Q~IA!bUT&kPIQh&Z(-h^C=Q8mgRW{$LU*^lwBKqDvjN!ZoP)9%Sm5$BWTAQo? zNP(Q4W6Dyn1Khj5ZK{xfAd*^=0OHAZXskGxhpLUQun9M3qJCgWCqwMz`(b}ba63J5 za8cx5QhNB6jT03nCHAC_&s!OS8!TDd1H|5%VelJD&P3zNDVOaj(NQbR&Q#!zjGx>n z3HI0Uz>qpZ%x31R~WApn1Kcm23s>5QF7C*ZeZBy3t5wR69VFXwDgdc@pf z`uTpnpB)E#;RFHW>e)=6S4@;7}>j^c=a=Xe)u2@ks3$?y<$@5qpj`y(=X%c!cM^d0Pr3+&Xa7@oJ7zUID& zIO14Z*sQj=-y`ez$}b6IV3Xsub3H)HgJn#r?6Q%4-7hUJ{*Ut4AeHbae+gZ>X{oYC|*-gNpcS{mbOdRfV>zllfu;#hllmAxKq8!7} zD?RdIKBL0nr45#Nuw1L8cfQH**I=&)j%2INZn6&&OZ6c`Dl+msUw|@ zVV!PA!FB*k8_AwVQUr66>r|KNC16%U<1#9GV4Le(9%+e zXh15;W;^MS&KYh??eD@$FVx*C^|B>Gqpo+UM%#)HXx|`KV58Y$;WJ%Y(cOS<`w#-;R9ZDF6>5(d<33DPL3`tf@ zC|glzaZXNz$?T&@44`l18UnmbRi5Q2bQ4HZwkBtQT$;vN!dtkV5t5wcIkmO zJ+ix<^WVCF{~c^`L+2^i{vv_BQnsWeh z#Fi?F2xUJvRnau*79XXm29|LqNr2$0C4E3=8vgDI{}Sw;eP_u+UW^&aAMWLE@IYd? z)$vKrknlPG#N^BLx>bCxr&EKKETz~6#<(hp?e)9}ecxf-X z($|bzbnmJu`yAx7l4fqkf3f<0W_vtupqWtmV-&IpUmAkN3`-x*{7opCs8@LFYI6Df z!>*62%L1TgC_xmhMsw}$tki5PN-VhFVEepM0g@<>9Ivn#RjbQuJs)F|*+|LW{%=dK z3Dvsxn6G^4O+cDh?C)@5E5|&cB9|}(Ttk1u8j4K>)X1aO)O$y-f=xkYS{vKIq1)|@ z&*b);=nh5$>hYyZV{`CR&s6F&#ptXEnjfRS692IjPUJ)r++)ax>^FSxiS7wo!EjO7 zLFM6=D}l~t(kPz@%DCB6K6F?tW71}5&2D0~OGm#G`q??a+1}*8 zuI{>@rGGx@YAW?|eFw0mge`ezC0vjdM6Ph1#hAw{7Y#{>L$7VZGrkcS9icis3`gU_ zIk4@mPVMS&>i79Lu9Csc%ni+=SX7r!?VUo>{XBYki3g*TkC})ji2p*j8KBJdn(yNt z@(Efwh8Qg_jyS@k?5rw3#bD%-<6Xkf=)|AxU(0?GrWb{2EVFj^67U@aK3~_i59ld8 z9MY55u)Wu8K{bE^a;~$|m^1)R3?t7Vies1B*>0Exw z9`qU95TptDOz1YtX;*cIOm@c}Lk$IkMOY+1>Os{JX&3HWQuZdT+0)4rcb-`;tE#`K z6jyo0(lfk-C++QFb0YdK&*Cp&!n5-X?+`*WVGF4F3|2IfDrRVO$O%TwU$gPHU2u83 zF7)Y{wTRv`bm)}q>fMYUBQ>~<#Xka#uu%`W`LtK1nKyN2Cp%zC*Raa_%{=_VTjWeQ z{|9Y3dJe|UAYe$+Vr#9gk1~dExZ*I}homD82O_2lQ|e{;b)>%gN1-zOXEQ=!CHg!rV?4dc+S>pSmF zM~$n(=qg!ml5>Zw=sY$1!ph?nmWzL`ZyQeihGPz1Mt$gi8W-Z?zw8*m&u7eJ2dTa0 z#KJ0WEZbZb&vjv>Sw)q2axca4i+TsX>3{$)birf1Sm0A>Tw-5Ae3s~s9eRd$Tl!w% z7Fj<9)WMO~az=NU*p7(F=d4U8hB<`69Ky??9*#83!$sBE8V;RVH>pQCf6gBz?7#Ep zgq{B}A|LLMG1~9s7o1q-l0umZpkCdaN;DwJk^6#MOB!a{pfcLx zs!V!eVM}4eQjC(@so)`~t<6Mk^)BTo0Jx|GOMx%N)qQux<}aGNi54H=k_^UT^y}kg z^PFg{3rY2NMQ@2nW;YlQ|B?zPql+b!@Z&5H`=Uxm{mha)Qf zhX!g&kV?*{SKsU3L4D7eh-(AQsjx>k0T{~=vsJRU!Oj6Ywzk!Ru$VThnoR0C1vs|1w_lqp`wNgi@i(#uYIZItV*i${5s|oA>YUru-K&{LNgL3=FLY)$w za4>H(jT~XV4x-3-M;=7{(=UQ;#xT{N6j5#wzczL_?S5QVJ>R4*4;cC(a7%UFN6*c~ zkm<-dMw=joonqkd;Vr%H)h&M2jleh-Fr#qW{O8S=5#Vn}GagY9GZ-4Nuqg41rWBx9uDlvAZO>6_*|#An5LY9XSxj=WFssFgt|sA|2~OV`e86cLJCnukf^gq>Q<12v z1mG>^9z>2Y^nLv>t)!90A=lIWdiLl&pi-!f3b~hc*adX&4y41)VPyyC@)`F;GN`!I zmhmT12Ki@qne5?wg&q`nME&sjM`IFz=Ddc9i*5F5!9+~YjW)*SyiJnT^gQFlV5i3V$J?M?ctApAuv3_^AsB9?l3E3#EQ4!45~Rfr#MJwnAC0k z>T)f6bH6p6Wa9iAAUq&%yr^$L%le{MsJ{i9Q01VXM>vpAo6=H}Gw2->I8JI=44h>N zbB*qe^w9zAMIiy;*a<1Z(np+xaj9@8o_T+mgN%h$z~PXc!D21X_J;fDXt2cqqUIX( zlDJAuOBFV>IXHZxnCAq?2E{XNM8K5U?9DNEke)h<*w%{T zx@=3az$tC7-dgI75L6U-Bp5EZw`F3>T2RW!CGRvB&w%sW`lSCW3fXnDkCZFPtcCy? zZ-^v%|Mm`3Xb%fKFWXI|vX-lof_~b`;8E7!Du%$HrD2z%OYeNcSU+t2(*ih7M@I0x zoHD~Am`d|MF~%j%aNobZiazp~kGYB-e;yVVa+!RRi7|YH7|ollh4)vB)MHYZy|s~v zSE9~JYhsVMF1&yUNI-NXk&p1cp=@|TneTsxUlA|Q+e6j$lRW5MKVr+fW2%E@z~KID zYxk$ z(8}dAh2w$707T<1`*6iqff5CNkVM^qY!6!;Ab5-!3k)ySw^^ zxl_{jdWtc&hjF%scOdsAv$a?BJ_aTHh*9MzDC>~qg#&RKDtFNIro62qDSu1|P(XpA zCW3G>S-;51&4%rv?>i2AyqbypQIs5KfctndGdwk<&yyr!fe#sLEKsh0ZyDl;wMS>~J_;J&V3x~zeMVT2yDA@vG9{-NZfneR z#zFE8UG67+jq6+Owyz=w0*oT-rezNk$|MD$FD`63n#_(wbJ!3&pM9@3%E#45SK?b~ zZS>}9eUYt`KECkA687$tj;Fz%Hwa1A5ug4*9h5i*Zx7U6lf@k`iRu5^}}Yx^BGf9Y*yT~Orh=;N~S1r2j!yrymc zF57X5Y43I7qzPozbJJevo#z69y3(VN~zkr3t_SQnx6~FMr3%xwwLp^ zPXwC2dhfTV)6l;I+(`Igh1~$aqS-mXPmPafE*8Pb2|4vD8VLd$%Po`OiK8y|%wh=FFl zm)xlKpt&+chqiCA@s;0+oqaFc+i@AY+#AT&UwfEGj9+;^Nzh$;^{)GFiGqTud^4MVPD_SSK4}q416{5NgD+>glM-?qf z(7N-`@?8o2B9H>T!sC^spvX@&NuCm7Mpc`{bTG9mB3SD#R(YoH~NVkcKSg2o&lK3YUhd)`nKfjt9WEim{6Lnh3=+Z2Gp22o0E6k$~849>eV&4f!_pMlEMPOk2pbTwBj8P~eeOInDm^s(Y9n29_RIMt79QS!1pW zVuu*01XZ($H05cJk~rAjLH*bZ6J%7SFKmBjVj#1S0KmCQnQx9GC}?!s&iF!dBP`R7 zetE3_571V7#~7xi^dO59=p@bcJqY>%>F;A-dVKoLv+U$PD~01=2>|SvrRb8 zn9<(xoCy}J@s@EpGrf#O=Q5SbvgER&19vsNG^hwq?UcP;%`^K}sp0pTwrjxbWdB6L zd{*3y@5B7n4{{;u$~BFPp5$g(*=5X&Yhp}^510Zfg0vDJam)J6J7euwnD*YR6_CE_ zk_Mm#iJ6RpR|3F$JhZAvb>QN{V^Q~?zMgA@t8W|*n3&nt@B8nT`#&H)!No0X=k5() zQBER7+T3BKIwZ}U8n{2pZJbMEpo?&I#lc+qPiYv7^08TPLPR>6_FRcV#ISF1F>i&w zDV0hN&El?asdRMgeZiR*o4RXtNV&40S%()qY5G+_Sk z1I6;eSK41}&p)>-_IEWiu`QMm>EVc`LnI2?UiVVAk870mMyt+3ZF18?IYUA$joQaP zeo}Gvkcj_G;Rw@x^@l#X)$SsnXb-dfu5M3Dd%CjC`BDYq6Y9WwINB^}!O0K77v1-_ zQH7YZ?+{U@V-MuoR!~NwgujZnp@s$+SqH1&GiRmJ4N&+?%2G6bnAnSoyPjT7#TJCA5YV77#&MXIg{F^IQXqM8v3` zOM%G3LX4wP@XaZ@XbT!l0~mTDr(dN)mu- zhvrIv^OAGGk_tT7U<0<-*)6;UEWoS0rGz7-#3IT{D_|2-1O0^c+T#d{u_om6f71Nk z7-FA{meMZP-b2Y)T@o?!Em7bm=yTYHhvkpUBzk#=3!I*P;+*$6tDbiCj)T8qZo*KQ zYs{H@8i`Q32;xF{ff5?I$w)^Jm=Yl^X#O_-M_9~TVL9DzBuy0hPCg&FOTmg_5CE-T zPlAgMMv`if+Ok+xsqilSe3Id1ES=gXMeYWV97x+sqHvA$dpZz}E+&peF#N->Ng}3# zgn3bil$84`bnhn&>+Riw&s?h&FrniHR&H$b>DX%vZ(M+AdUjg7)#qaTV!OtI$|yH- z+`h!pQR%$dPJ7BcJ(T3Y47h~VNHgT#UfjIj2$;_ES7@M^DvyY(LpX19RNo~6x!pkCDC*Q$kVs0nGZZlcN(xbn;avE9(fE0hNwUO#%9s0fi3&4#4O^^U z)^`$I9bK^NY?lg~NP@2$%=t(Z(uNddK3{p?R?Q zAZ0vG6Z=mMVdu`+ET-@fCI5eKHlv8Jdh}!rM8OS6rD0yw50Mb?S38jid$uK?g!u!IEt?d#v&>9X&@Gq>4ygmlfF1>mgO z@Y?#_jTQz!lSotUAaQMK+bM7gCR)9Sf>wZRsT8eRn5oq@mFAl>tT-L98=Z*P!95@; z0rOYEpXzP}hChn=%Az{;w~k7lu)QIn_?W1RDg37ht^^iKyzGg%bbVc28JnZI`uY3n z0rjz{`V@AajQU$4zb;`Lmej5vfzYB*WV#s3 zi!}Tkf3fj5f5^-XYv48O$(j~XTYmAcS#aZ0sGmUnn9j?Hm^UWR{Y9xj%n6Es*Ig34 ze@u5U*pHTrj2B3;tgVZ=FXy};Z?_a|5Ajnvy!~WX6ctx zMoIC4k44`y?d*eo0?byO(~~I&m0oPp;!|~^PW4DB67m$Hbh|>BmoF1FzgUc9{P;{o z;}8He|AnP=+UNZmd4wK-knL^xz6BSr#*2*hbd`~VsCH?00NJ+1!}&qTmb0-cZcGP~2{F_PQ??ptqrY^|rm|sh7rV)w?}u)wJ-~ z&3phCMo9-To@DqP*MS?%C_O345~Q=id$Y20iiKVM+j3d2>3;l*Z0vH{(uE@xT4e9r zq`GZ6iU8Pz%RD~u!8z_R+3-E(1h!S{rG&36hmT@af%Q( z%kaCVP8hPN9_h{<9nB7z;F;^ptPAW6=hJW7&Qx+%W`8(1{PzOz*s09^c)kv$WZp;Y z2`u@D5>#qPmE8D<27dVYN(zn%f=u`$E;OClf1Gl(IK(}NuHRTgVlAGo7bJLrAACbu zmiJtI{WIr?LB!QzRP9>?&~99x9-%TTi8mvQP}ii=uw7up! z8QrFhw3L6m4h4fpcA@yne7({<&Rv>A)>=n5=m2z}e()v_BM^kz*@93-eONC1%wIBN zAVKBdCjo0nF?pLH6upM6V^%&qmx3y)Z~R&srO^&srgpzHKu6E}P1u)-3_5zUR;M@a zc6__NwSOs|Q5A5em`|_5b9{N}n?5dA2qM116)E99v-%wr^!TT~_ve{ag!*nzif+dx z!|QVghfd*=M?+1X*SH$05KNwyhp;N7}i?M7DsCi(-nRnu!IT07-A^Re{RK+9G>T) zS=p=M!sipUt>ObR=mq5)PRJC|q{M&BBbFFmb6hQ*)il8}_>G!D$4PRJDQ^@MgQ2CB z79FJ;>R4@w8;D{Y4?R!ht`x!jz*umL*p9pKnKo88`&)WkqQ3SV`n8X9np)GY0EHmE zKO3f)3OB6H%K)%+Fxq4&>~lJ`QmfXXB+6FSs6aWh)+gDJOgCj@)u*T2*{_s&hQ!I* zH2{6mXk`TX}smC=t@=DqsTsRbg7G{J>nON##- zIzJXbSJNT%O>hr`3rp^(T1yBbRaO=zRtOiiES^iYQ0;8<5sT>2HTiYB*VfayXX*Q< zu%5>#rI*Sdbvk$Wk=?O|=J<6b2&C|tMvv)Mdj0((qG&+MkxAb!N4bBt>)w6YMZf9V z;BVWWmN62?G6HP|2vvZYp`r8|Rn^t9S>HNKfUz{{5xTqi3AY zBp(Yi1{{v;DyPU(e@KUJ8`_MN;`!f0!vc{`Dv;?*wdfitSpYeHejx6{pl)!m2Sp|i z%zWA@a@E??U~>@-ObYl>j+3lxop4ClYszt50)tP`;3lG>L*VWN>f1 zGx>Q(ibAridD2Z$(&ocErEcorT*88IS3u4(;9({(6qUs-`7jH8U{a=U7clF z)zv`zoc>>S`F|<6pORvgPu~wS^HLu4N&7z*k7Rs}@IdSPlj=_f_;Zi+mI9wP`{y~- zz^);?&A~@xsGCVRjVgL(1vXV8!i$>jKN&e~g1*fL*_+^17sRICRLhuTKxwRqefh$t7;UmPcQ_pTBhpjpF(4YUyVXLbA3JepyGN;W)q}otB>sPS!8v8_T*uEV zrRNt>Dim<*bbmA@Fnp8h$LsP|Au)qKc?!wTkKROpmI+x!?1kv(`|X2Og69*~BI%Xt zNR>T8ldZy~2$WI(L=*Q$SZIaZDy5sR9@x@oSs{fZzgd9|yL-{?rk{6ePdqgD)hP@3 z=Ysq@0YR8vwxf@}s$4U`gh-x*x6Z*i%GsjP8<}w96m03P&3Pu1UT=?Q=7y=;RT1Os z?v=lmeqsatCo}meoy&0=Kab))1kxFy5FI*7117`4_X-%1i(IU7ZRXOrD|7mU0pccz z60Ki8{j_KzAoCTU-tTsk!lKy_@0I9tw@`aX?8`oXLX)L9?ztn41NS%nK9RNPfkwz%;{7Ko4-=+%dp(IG>gF0r?@vpX`>>r+6W=m zq>w_};jZ*l<}U_(%}X;cT;2Jo=q?wUIprZ230P9}e;)KRRc^BI?}Fe?(Kh2(aiITv zkV8K38x*sQ1k^@(&T5rQ3=T_X=X#P_&=>I?&_rNwpO}wMT#w-2yvj{2r0tl5_0BuQ zm`-~>fLh2;4%dVD?=^JH@*+Q8w?wRmi4O?YbhCf4RLrZna=+iakTJ@`UYE1T%YHj{ zFMe2M8aav2=s@qmthkb1tl(VXUd?jL&IYCafQ8zx52D3Mv4-O^c z!(Y@${&W4X$3Lg2Iru@)f}s3qdy?lK=3jM)fC@nwKQh(&ooBgmKct;&4^=jx`aBIk z(Z}!{&E~VTk3tA)&5~5bbqf7HjoKXzCvs)D3f@aRWnlOVjz!3dN-r~*;1pT5)lD(` zJO<>gy6tk&dC~gcN&3kRJqVCzDvklQv^oe9nIzE+^%xnBq1%yyhpR|o(!IUZTclVx zru4})mU*3-h)yPkjdK<#g1Q^pF+wrq|AMSI7K5be>;{35oA_v20t_{#Y6E?kUl4Vm zsM?om#;V$HKP^SvX!B`5on~rA6-VMnOgVU$O1dDE(&lO6(SQE<(%KqklF;TRPPDHt zSHXjwJ!$9+AlvW{RbY(ymjf2?X`8Y<5(o;UC-OYdu zA_EjjWq{29TmE&MuWY=`ipDBai<+gX&B(`QI(^zV=+n~Jx) z1qav8*<1DYe_`cdpx9%-cFfS;^JNME3M*f6RKA>w>2aeO7%9+> z`fbejQ(q~rp7Mdi2$Aw(9gEy{{=w;YzH7Ydg9jUaDrDzSIBM*+?^y+|agfhN2j7FI zqBRZPlMwe%0;Wv$Mm}(QOJalH58(|ss^Ucnc&&bAe1ppH&E{mR(4MB0drJjsp&L>Z9M#Yf|xX{RrZL%4xQH!se%pvd1pq=cBoqt0@m&ir3rqPNo5K% zcCgv%K_`}M%tWT?2MN?CXqjYqJ8?s0hy8OmmW6!w@|R2>Ef)ChF#cg?3P9O&4|Ds| zZU-}iDQBF93O6M-A4IAsid(XjHJ5rr17?PciWCu`Ui5dbGK%1C$l+HBB$kt;ZwVui8K_ioU@xmv6ZDUfzAOK?-XQom6G8{?_#PZ8dwo zPVVAM@gM<<1K?GQ?mB(!w5TKCp89c+{7Ce24aX{9V*H(_KdV+O#Vo{~NN`Hd)X~bx zanmnmD~a=Vk;486WWE*|St9she*qL;b%nbBzT@$^{fBzBK=kn~?mrHr4a{ftHBiQQ zX#SZtSU~6l88b$LKkS<e4J`VH#qc3kmh$Cph5y^Ix z5MvqMl$=M=dCi=wiDLC`uL16$fp}bM0@a8}*S+EZYXT_woLLrDY~FtupnpD}_~xTCrfz)mH?KV53Q&4p)5E<^N21o- zePAr)Ycj9)vLz2AjfdG7A>h3(mmYdF7|h7hJ~_7*wdF$T`qExM_trl zvcy%R6m(jG65qNUw0G^Hw3(bpK~+_m_#8oH(lq{Z-~=BgjaZ=?cies9FS^H=U0bY^ z%Fr9P$H5UcW+Eu#&a3K}d>0PWR-wBZL>X9@@n>-F()1ySBr!fPYDPLcX%sBI6*gVt z;5q+}Rhg5xs|V%#$MG}#bX}jze?9Gzr=JtcI9~UvY9hVd`b8G<_~(Yu0L&4DtxwIB zsab+XzZbIHKoA^@A_ZbreDtsO--XHz_cmcre69sh){2%-EMG<7<{M0v(o)S@NisB0)R4vfez2+crfdx1Q+?KQ` zkcPHlTx=OrJy)#H#Jeec*`@0&XclsjB)t>C!D zJW9ICvp`HHQ;@geGI51vmLuQ*_}Jhuy4#6Dt_TTuJTDcxW%VnAlT6mGz59!E9ml@U zhEd^Yd7L3R`D%)1u}>BGW~hfc1RFNYlJdOC%+EF5nxY0lp#$$=eSuVBlxNKxXR;A# z5Z&tAeKX^wycllArV-Np`IR~Z0}a_jNrKP^B_ zEE0u7H&U3)FlRQH%FL<<$8qMp+e&v&X{gV_^ZG_zx`gEV>t=ek@7M1TUaPkiS`id! zkn71HwleJMGPbp8&pnK@4h3$B$3Yyib5WNa12(7eMg4Okm7{#^+uG44kA2)skOt%Lv>2paAwEqFw*uU%TOTHh)PH{1<90zRPX7 z=-@lle|G&;3u|d%r6xk2lx*%qt`PdB5Uyz{@v%Zq=Y(K9&1O9J2=-68TR^q1(Ta`_ zw$>n`VrgFV8u==PMjVmFQ*(Q&x(WX^${x>yM)ratyeQVBu4RvR`>$^HTn?~l({Lw=Z1`xhy~>SXfw4;OnU5=NT7zl0yF zDoNdG(*YE<)>B9dk{g0o*W3}g8I?@lDJkdEnMe$4NepQ#4Of_)M18uhq(be-{Xc%h z>~Pbx!NNFo$!-tu;RUj3M^sb?!8Y6%XAl53O=OD!0oM)OKiqT~Jf=7p;q zY~}$xES7*FK?<}Fzuf6CyTM`212XdzNRDkXNNs`8la1V_Q=61@%sdj&rxHl=pC7&u}~fmw&5E-Pz_E_trSO zC!CPj|6WM)o!FJ=QH0jo*0V?PH|&9+C3OwUQ8H+a0#-|+C5BP?2U z^shqB)fiJ?5@Zs8K?OO0NUk*5rD#)|jlsh{O3D*TZoDw-DBV0oZ#)&A` z;>K)x-=R7l?-+}G)!tnB(eP|76Iwsw_(Kbd#(nh5L|iwTIy6AX_BHW+PqNhE_g~~` z!mxPphxoyUZlq>RES{p0;SngOMXMIgeiT5VG8_qcpS2owLOn{YJyfQhS() z_Q!PFOlEOP=jlE=-4%7Um!4nNTcCt#5G8ADy++dBQS__K0CIzj%-+$7i_75g6p@>3 z7VDnezf4?Q8TD|q!A@2FBU%4i-`z5T3MfzfJ+&YB zuY`Vc$?hkrs=i?1kbnUWW1iU$4IU02t1m}j(#KXAIFnpii!oP}NDeRxDMLl#dqNr2 z!U=jlSeWn1@FKs-eeD*EYYNjC7d*tTJ4w+Xywm=`HMJ=q2?nz=4k)%58eXa2l=DBY z&dNGEV5eFDo7K`R=!2%y$bm{uzqGSfwIAD0?l&oZ{{o9{#xZ~{&IWfcO#368@U=`L zqRQMHVtT0YvqE%If;ZQT%l)dqhD$Dx0_Peh!?cegFF)YZzaYc=?_eM%)a!Qcx7LNb z@Y-RTA^mV0aQh?pRW7BBt@+U!9{M)0CUQ!DS_ul~R3N#=1y%r6rgFU^0PO@+8S!~G zUEU75*>M_BtclCsf3ay`g-3)9y}ggws2-ft1Te0qnC^8!cj8>OduDGA86R!6>3h3n zjmWTbWBDrhY6+FiwslA@I zw|-F~LhabVt<5#vMRsM1`%W%f*X$EMqbSrJ2|?u7@O@V07L+;mnrI^6BFXGW~FVJqgxA z8^{=nES5HDQf~iHB8S!GVqVn8kEf?kLr9_eg+#!bFu^4OO>bV;c1Q;%L^0lyj zdT(Ig#g8>*W89o!OV|oEj%>Duj^db?z0C-IA7J~A;IP4^A>0R|a#nXG_o&IY+xIV{ zx$cg%_r?A}YHP>dP;Z7hUk($?)F!ddOa|=_%SBBR8zzsFfD`99%32|G7@%<-s%txK zu3RH@f2NzyeqR#W$gr~#Kwq>3E)2qaVQM-HSpgk2Z>C;ez-cx(CR!)Xkn0_OnfviL zh8MA!>w!r#VGf9tvEfp2ZMsFOI5}yv)2yv{0Wd+GoiSPKtD-d7iVcIz*#e+vlItPA zHj;;3KDLV#xRPYvih2d?5Vr|)MgMEexsijk{-k|cKZxT9-ka#*Vci!G%0JUGg^49} zN`NSp;X$s|Gx7{$dx~NT&SpI#PDe`!)vGfJ(X2Dyb%idZFq;uJCPE0j3X_5uDqd4B zG0rhufH}%PFUD`^o*`!ZKC)-c4%~^074!NtuZLavx)BLEb6VYVf-&j9@@=$395RhV z5~z{gwa2peIL9uCk_ru^S18g3bA_cg#5t}_(M_wcUAV)oqM~E}$au7(7^~=EtnleF z!GKwz5O0)We$Nx3dPa<5q$s8T3o#0kL?p*PRyU#>w75vmugZEN4{nca4_MNu?@-s_ z@NaNO4WcUBE8vuZHnkS7*NcL}7r{tP6bx023tg*FZBLAF>rJ}AKRrg4Fy})Sg#yz9 zxKY>S?TPv-*2dzlk0ZXtf`PiQZcEfc&7!aK8}^X zc3FW!dpl`7-I{iPoc+bG>)A;B2<+ZzJbrR{W$>JFFr80txF}36r3`uPFX<2QIuQ@; z61g<4rubqo%^bnLrPDM;4l8htbKVVGGKRl3$0+0#EXfx3Yg&zJSp2HwRIcsn75(Sh z3H|{OkFOkkEqMMG%Jv93R*;)05Ys6M11rw*#f$J(+nx_+4^G@)9Z9ms|-II)z4&K71d-SUHAXdzvFYjqYY=(_M{aU zl08l2W>h&_92xJ+-cU-M`Takp-oh`+?|C1Vb(Iq7?xmLw>1OFJ>6Y%2?pi>)8!72- zX+cuDq(eZuyPj3wpYQMa2kzIId*;ksbIr^dj*1O{U~M0(t8JPTqGDcm*X{8_bXr~MEiuDO zUA*l1SX9QP0IlL}8@^W_~$j{nWST?=>pJlPhyEQ?u6Uf8@o zVR(W9r3^bT=heM$8krgW%=Oi}?8?#Y3f z=7=+3mB@2WnyO}bP_)Y3Q%+4g#SucK@bjfgPZ1Z)@+q4&5E9VT)5)npc%KjMYxA1! z8n8S3Ox(=BPrzzru!f*!hf!>EUPS~3<}&(GqKg%ey^+twcCU)@Y$EfC3;6gpDD=8T zYhti)sR%7mY;G}F=tclS5EP*j4%V4jL%Te^1E%ya#=>nV7Bc6j%3-HVP0jmJ3xVY? zmtN;t*k1p$0Zhv3-RXVm*Fv{k@hhSG88pgDz3(btJV(b%0qozY1;}r%U>;;L!+e?r ze8Bs4v{uUqU~xUk`o--7P&e?)A?g$ZWKk$ts8iK@7QXc{XhVG19B6jlo_Bk#@2a9G zY8^P56`miHxEyJ8c=(_kLr#!w8nAD^{Dmy3}v4ZMry?JPu!l zB_G^>^8J3$x8sDab~NsWg=aqndUXQq1E&Vc*zq|GBd$r^Tn63h+Q^yqi*C{#Sz(ia z+_*+VB*UU;MobZg#qVF*7r*P|EL2_IpAl!Z|L-+AADY}y(sLm;he4VQribYRI^C{n zqmmls-DV6LafHa?gArJJ^|%0_I~Q`o`zBKwaY^|5!+n&G$IauTopwY21NL$TuH+~J z9{GeQIX0%$i*NY{^fx++`&I2WN+lWL(Jfvz|pze+l-dR0YOO*WRpP|cv0REi28S9pq=phhzL>M4g_%VBF%K4|v*qpB+ z__bJV&qs~mn6zB?)z;0rMY*n_ObqiWd^wq*&>T~M*p}mmEDAPdJuXhpMxpSh#vk8m z`TjGnR7^N^o=stoo0wIiA+$CO!s?fmJ;?JS=_KAi>$$#k+#16YP#z2i$y2xDg33{n z`|oRE#AADo+IHgJX~IU>+Jryijxr7GOdjpi2j32R@1tuP*7jim1j@OS1V7McEv()* z)cHKCI+J`Nj_tyr5+-*H&vqyIc#mKM_JBBL>!au%KB|2)DfRqlKKjHk zOew?k7Sg)4I16u#I{!eH(TJ+d_w+s{s)g=!d01Mad=!0tFeCc&q}^)TDK_Pa7jTr} zc8srm{5}DUbB+E~YD|dBlAt;agV5kK0aQ*7J=Cu;I1v3LGAFFTQ6?O0cs1!pg@y+m znvB&I!Up}tnL(%jbyGAG!nxh5uI87Tk5aOMUtyspya0vtO%HxG+DM@sR|b4Vj%mJ> z9bVCLR@U-aIQ-UH`xdza?dqlY$V>IvpREdA1#A>K_>E|0Gco>wc-DUXaZgrbD`6Lx z`n94Z8LfiS3V(wnQaJL>FUP&}$S$qn;TU3ux!m{bJ+FiWP0ogA^#C||Zy7P$0xX-k znJaIBfq7l*;v67JudrVZu|tROl1T70=CFME+T}mL6z~75N(xKJ^>~V_R1Yifx#gVGa26sY;{wdHe!%|No%P6fjtl-0Jn$0qm;lZaP_tcAR zyosfv7qZ=#`Rjtm$e$nwN4x94BZK@~D*nuNT3`lD293u@@y^q$iJN%+MKf?~9S`&Y%%& z+*M()4bTxye5wyjj)XTBg*LT)TibB0%;jf)gYrdMTc51}XCnYigF)ZBuyRG!>tP2$ z!Iy~b5Aq7rcbBNRsX{(Yt+y}!3+yHrFJ@OGghSnCYa1CxIo3-y>T2g>~6>!P^q^?w0uqAd-@ux+T4S*{`U%P`Bh3oA`gx6FQk7+P#@J0X=&`YJBc@( zG(;-|2gP-PsJo!O;@(ak7RwY4@&YaEv+eg|c=SniN}hH5mg$IfP0BoSpP3?0_qrwv zy%K&682^NA4~kHzUK7Ts=N9=yST8j@Co@$B@3rC+U-1;3`VTNm8499V*mx|sdOo|2 zf(!RQdqU2QWHMhOGDrbROp$Oui$F$5ek!M;_|it8WrNJ6ma3^R(Q=1op*H&-BiT7~ zPpt%lN@J<2B6n=hPi!B~FGxfDqlAssY@_=UJAP`?>iS$M9V3S(wc2JYq)mYWUP+R9 zq3Su*Z3jymW@B=fd=NOl=vW|Op3RGWYec6()ET@6kp$hi(7IpX?;F5avT-zb6NE5U zZ&eJefp8zmB1Vmm96fv6ad%#CL)L#TXOaJ(GtvU+A5+=a(u+yiuiXW7Vp781s3jo0 z)8cierp%+MTeataKoz&w8+9$+Yp^oWf9kgUO3qPRY0ficKDP9T=Ey4b04?%U=SG>v zZFYCS5@vH!{)(n+bu9FqQ^d__97|MuZsPvzSFdKSliuM5=l$0CPz2uV)Oo7no$hZ7yf1F$8D7;Z!&D zKgiaWue?j27+Gq$ym;*JF%5b&9vqmoIBIdTy|*$u8WC_iUKM0F&#|w%tk_6LoJ$r| zq51%Q;RT^U!g^Mc7pEq0chJ!V458|X?FDIDeE6x@+v}mWDmZy$wOC}{*~lfcTHoCM z%gr1h=a0w&NBsi6DLm!rtDfgNmvr?zq#RVaHC=>a%574v2BKquXl}4WF_q$f-EtWTGvI9zr&3~#6eh~GisB64s;4UpWa$`S zR_9WBItuUGJeLWX;LlyTnzuO1k$nMb4iD`1IyRk)7$%Ufv^8$~xsR~36Vuhh9sqom zx11PTOtOTN;(u1GhH6@ED=Zbpy2RKvZma^5n`*F zXVDFGrPY)YQs)wB-+L?*jZf*s)XnW4<-2;lE34jDb@pDaM%^=V)*l@2Zmeu2zCaG= z$>Kix=!>9x;L*wRo{q%%joNF8bVx*)jI9~D-6#ZtOrAytNe zf%WV^Zqf4gqWq-iWBlr&2oP9$hdz@2^1!s{q=l%?rM3Qj=8B3#wstV;c93ssr{RD0 z?GS*_3*T{abGLr|utQs}D%D)vi4j|$94CLdau-3SExF9 zN=Nep1(nvq_}iM-8sNM;0>*BMS~-Cs2whA5!*G+Y&jzDLjKo3Ee9+XF=hS95q`0l5 zjj_ye4q#$lHC54c*Es@yAy<{&5P@XQD6yNh1HuW|#9=#La&iaw-RHR~8TVmY8id4W zi^1~ZE&3%6Ss|zBObp)FJUS*X0w(C*UP_5gz>H4vm3`DtmCxsF` z=41l+Cifx^%7UJ!hDtlTt{h$Pp*SRQ!;M0H0y>@hX7yY&XM4$XovX~x*JWoQp-~g6 znOTS4H&9W92tg2B)z%)KB?K5|YR~Q3$?fy{q|^T`;1tTa7O7VIA$){~X*t*6G(#+Yd>BRqGq85YDy6$ru}mK z71~9WeNLDmX|-Bm=tv>PaI+p>3_?Ru|MUvo0i5(+5+PH`$YBX5$=`o2BH9H{orp#{ zjwI+7Jz5MsqIQHj-Y!Ci{>X;w`3RcW=Abp5w!!r`n!KTb`+9b^D*b@eNS2`~TrR=+ zQYA~CNrgAl{AJ8tKQNIdPv%|{m>1WD%le(seoV1mzBS-jIs9rm+xz!D#c@+iO8+2I zGMR#7M9+se`+`?A&#e7|j|H)0FJ8_n$)m?pgS74EoAmXW1W-d5;_61D5Lp6{MPRBz z7D-zTLVOScl9)uA+g@ei!+*^u0DB-5@DiexyFjR9P{{8zM`=ak7B?{bzk7l8Mj*e6 zWt=5MTLWB>2*n)}C(aX1$J>8|I$wvkC@M5=o#Qk${h!me0ruABw96+}wF(5Xh@z{o z)odowZL-+O8KxrU#zx54&a$cNzH0i~E~VF7sYR9EFgsp=arXvq&hC0Nt!4RRMTP%uz=Q^@uQl;Oa-*2DRmIUqaLYv11j}E_Y9@76!pYO2!h6d z_!)@ZcZ0(f?)l=}tm`hT7WvL{6l7Z3P(4TW{&~d!a`H8GgFF3i?fhiveMc#%LIyY( zVITH9Qom5-dW#;PLns3bP|8A>QFyHkoYwrW51t?HetXUB7i7F&oBEU$8#Qg-&#e%k zDKXRR*qVQK?juSDYhHCo)Ej*iBVN?e~F73$`u13=~pu&6C4T&L)w{Pz<{ij`0-Dz4QEXB0#0vC`heWP zb!BAC#`fjvW1Er3GdYQ86GyKf$D_d1KYrpHMEH~LIm(pZbW};WF}*~9aRbjEr_LTw z?r%z%hwk-CBlgg$p~UVd$Ce$hLszTW%z6(mubI9Y7{1@a!zY{IyGnXpW9*kKvPkN% zG+n0eD-A%cfu)5t+^5bc{oC)lF6n%Oz}KH%^yD1Q9BMnLtoJEL|m_R`7m>)%-Zuw~2V#gOH7$-5}t)p>NI zg#TeK|A88Wb^5it!Vj_7>vL%DD)SUI;Y8tkTzrw6I-DEcA7ni)wvRwt5(C%e&7rNP zt7F<`b2-CmM2CSX!!hOCtVdI|tM+@d>Z;{oQAijZrnrxvVqs~5Ms%zUt>-ps<5V3Yl zxDjBD)!VDzjfjPmP%R(c47NSm@%#->MvftqxmloE%EMhn9*>Nbuvm7;(&Sz#w2^D@#ffheI1|0BU-o_NRJx#jg~sqBTH~*Se2jrJQoW{rN|--`Il8 z;Y?Y`%}2kOK(Bt_>kJqI3=-(%ZzV#XS7Ckrm8Y^>$*RlEj-aYX414e5F2mnLh9B!h zetNAC`d}twRDh?+`(v}lwo$L8Y~}WAet@^9A8Ih{OMmZ{2MyU$KhZRJ&O3I56-!U# zeUSDRG878kll~SQkC(I2A{W*?5QX?FO;{x;7OJUJA)aor$hD|@jUmVK(GQBz~gH(r6 z$XwTOvgOZZD+ZqI!)`N6fG^15+{OBC^rQ6!-iWY-r+UzRiQ7^NJVvZkof0y!Xp(Kx z!l!qPd%WM6l?CkcNDK|*goAg3ttB)*yu@c<)*JPW1U`K&WBC~l75(^{VXtszhV#XYKf`$Ef6Y$a@qOFy+F!)VL~xu8QQlSTi9c2B-d1x)i!&kN(zz>mz6aF2vt6s!I9t6q18%HzCL1 zejyeANvF66rJuxTYT~2u%4BNi)hOA$u^8Cg!S4SwBm`%&Th{SQjmw9b-3qI4Z!g#y zoAWEMXZxK6v~}TN<2%qvj*K&QuasVdrRQZ_sFbPTk#3`xUcg5MMo*p0u#-uni- zJE_8f9FNn&-Pq^ciKnrx3#BcV=hCY1$U@gQdP$Nx(T>nIyR`cGFQLSSV@)!J2;$HS zYU0y1@}Y`jL@6xhY5AaJtVq6D_2uhppRkr7Il}?i6D`IA)R|!!%z&s+qTB6 zH@*u|M?2L}rpKg;TFcgV;9ZhG7z1k)E@rH?A|G5QE{+f&@j;oAq4uJ^U04T$-XiDO zxoKI;_Wf%H^SOvx%G`6wv{)fu<;k+Ww4~C}X_65jTNa5nuF)_eVC$C+pH7m%s%E zk;`YGpd9M+!vsr6IUt-5cUrTu3<*|Cnz=)JlFldB>`^{Y_@ zoezZvtiB>N`{-?Hh(>s$6^VIL3Yo$z?`M#dDdGF_Xrn34;+f>J4t4q^A3D8(VLK@> zcEte>p*q$bj_h2ACBT{7p~n1qd+Xz=L1}ZB#C*3Zi8t7Xb5hOH(9VO}L1Ub5m6iPw z*K0p(b?BVC`S_phjQhdRXNq?KSn=^ASY6v08QYHPjL=~!`niQQz?a&8VFN8CF&1G$ zY2-7Q-KEHoh-4aSSl6h$>?wDy|GfL`;k6Ya>vpTyTyGM+;RQE4!1}6nbxdrtBf#GY zOM?>`pTBRNA)1F%I^l*tQn~=W!sWM@wZy@7#k;=CH=kgR_ldHLRsNBOd5NC-!~kJQ z&3?w-dL((V`DEceIzA~rYz+u}(-MZ%x@S($*V2fH^ps?JuPO#?&a#M%7GgBF%s(Vk z7w|5^pWkU}>u12+N{Oo(Eu$voHxRxwaZ)A^xTcCag74fAfN}Xcsgq{X028w#J6udV z*u`5m|5jAAskzg6Ke63%x!`L}vK7f~yHqcZD@um8#4F433V70(&OLenFR)ir-Aux& z?hMvM0ktW6@d_#2dy&_}wa@E-cTQklBWrsUc8n7;08!ix8PUTl%-;rpm@+J|j&9XUqDh0e?3hoP(|pqK5xB>#6ZdPC zS$#Qv2j%UR+qvUdra)osih`&+k z5J?)n&A4)BZr&+6+wW_foZ_T{@~Z9Dm=P!eSZhK8gNZ93p>md#*+<8p9gn5B)-1wp zhyq#?SR zOy_MH{r21c^;xKFZlAX14`lg!`mPrAYMIW5eabbylm@y@W2~Lm2?p(JK$UiBg+^rb zFzRKK_Ny?V(zeUJmr0In7g}Ify#YnKMq_f&6^EF6Xe1s+9%QmZ(%IOi`@Y}a!47DQ zr6%&8oh07Ho55?P#`M*7!U3kQo$l?7+?puH8e;~sbjE5VVx~D@?#GBU&nh*ch;6#5 z3T84J>m-n$;S0ZJZ~e?nnvNYJl&r`#pW;&1dbUgh@ib}aZ7|<|DOIEb8TZLxjN6s( z+FU89hxh>_zIZ#63>!{%Uks1ejK&r5z%j-0SqkbGCeMYPy zRtH5<$G~)+W>OI&>?GO32=R|HCIwB~7NGq})2)p!qomdM|WNEM5d(qI;*=XB_)hGqEVh{5_0 zea-%S5gJ)u@enas_C8l1Q24kD$ydrAAbu5PFFDV@wI(&x?AfZ_&DMW3>)CKQ}c9W1CQ={l6uVU?2+( z0?)+O8qLm!-QI2Ie2H+y3l}F)`CyX7WG!7wp^g-#qmSrvh;{AE+M+BW%fPp+RO0I+ zKj^txj3#-`OMS%k@0v4^z_sj;2`=)Sm85t9jLGfJ)EV+hKgj|>d6gmsB15zgiAZ-Y zr&BXagcY6;mg3uK7Av)Q$+boN+}sFpke0|QW1I7;+WML6xmgGS&M#`U8`nCVT6;hN zyAD=3APqzekh&$#Gn3K0623^1u~N#wyjh&Q_o84Kt3KVWx9})**b#3S`Z}AsA#}#4 za>Rp)rw{njh#czn!0$vI>jl_H3em7Dy6`lon*<{?`z~E?=~4 z&GFPa$JB9pn%7ly%MmIKg@@}(|M$m#C5r%YG9|B}21^fih!{f19+R-x9yupj0?TJC z{35#SVV6-B-QYC*%BDB+R+j2uum~#&l>mbZEvKsx*AvZh`-<}%@j0i`a<;$4@A%R| zBPytA5MCj9cUtwz*6b=!Ma}p2hnjcq4~CCh(t6UJS9yu|et z!r8?7Z~_(!Mq6(+UNc+mYW=*Ef^f|C_p)jJL`-LvS9+7Rn>_LCyM`?5cbqp5Rxu03 z(jx!)^9_mfuL4F0$ShIhmqM&BGkO$l;>`~jp<6sJHto3gljir{aRdfN5GUiiUolJu zDxP$aP#*ywSiXOvioOQz%|XI^M#CI{hnsfjFus?23>7%+vNM@T>dpyqkPN%ougV_b7 z8o|{Vq7!i^()Gq_PT7(T>Qrnnk{Veo*ODO;gPyZP-OI$S>fE?9KDc@-P25T#0)7(6 zBi+7JmQu=LW+b{G*udkvxB3bA^_pR%H}gwAuVvug!fTKe`2#5byR;a=+!l&X>B=J4 z{g%$?)Z&Q|42oz%07SL*(39JWw60rfCG3r8SxGQ%47O~o?Fo3_`@DU;f0!tPS87MP zrt2eX4hh)#OPtKk#6a1nN#)PsUOPLIALVjx#*YdvOOcm_e1-lgYJe`FreT%iP=?~Y z?+{`oJ-#=(IxBEK&%)gSCXe)5LDR3LVXAz&w|t3I)Bmjd>T9uHV>K{cCF>b*=H(qy7lzlIVzHbDhhUS$9R z(5{6F&E&ILUUf7R=FO;7OVRIDcgu#8$am!1&U~~--2X0?E*fC@ka>BBC{r)#XV^vM zGCA|Pp$5Et?-_@37fCqo2Mnh>>d!~<;nV6U`)CF7x#TY;5Pc*Fcl%G+MS{YNHots3uKrw*@LB?Q2%i=}K>Ir#TXg(5`78>f} zN9b^LWSue zE8 zmQcMxxtva9TXigf7@w_F)H(0r=O&JP>g=y%D+-c~XBb z@Q8xN4C>ceuI(`<-lwvcrzttU+w*|OLmMic{>$LGEr*sG$4NWT){tR?qoC|ds4U}; zA~6wT`wU9~59{{xc9U>#k(K_z|HZTr@?7wd#?2DhFcQG>+FBH7bnnv>8i(T_as|>GEzN|eV0xp!_jB`J5WKEOg#=N$fm1X zE{HLSS->reFkyuaNTO?qtgotHKdCt4OFm@OEm>3<*W?hd@rf;JkS)gAxLk6QB?}TM zk}<~#4-Ew4C!0Ttgyb*ul@8vqpRtg zB1!L@cm}d*QeN_-hs;DmC?VwO(kbBL4n0Qhdq3ZT#>!{OZh;SgKfM_+K7r}tra_L( z97vt;Ys+nP%tvn3T1p{#NIuj{tH?; zrFZBZ;o_?K*d2WBE6fk;uVp)rMBq1=|M7>0#fZQ~gUgrqzh`OU1jWgF$#f1C98CaU zsL;rXP%=_MA+f=(uh}TJE7V=aeGV#3j;NBvw#!mnvhXJhUkdf&(PLz3&v(rhixeuP zwJPk?OK#g=2*DvDYLT6BsG=5dWjM;ouC;eG{_-_yQ@NR!G4ieY{|P3&0DC=ojx8V) z9gpjipVsl+Trz`Xo&rTvCMHxj2#}i9RGTUai79{zeu{e^zp?s;)HF60uI_x~$^vKj zx;<)pel#J0bZIfw%XTzuboqb!lIn8EzDoH(97Lujf^M$BClF%+f39TtN*T&zqsE~^ zm|CM;(Ar@7Y_x+<|MBayt#m%WG<8H*+$T!~dgTLkObZ3DE7_)k!iung+5MV!(Vd4=1?(?qpKN1U`OjN9Z$HE4) zD@JN+R`wU-TQPQPPdey&ICy&P*qa_OVo#*8Hl}kt)Rh%|DsX&DC$mkpF4ECcs^D(3 z^kMKB1~%5(Ff3M|YAJq>5Dz0ujM-kdkz}AIvje2WBnI$9JpI*vg_dTBzE=sQ(Z_$; ztx#XvF^raEf%UuC@3NZ@iJ5run15#YO%VSfUP#&TQdwSQK**+^`XA5Cu+ z745Ad&(0jf23#^P3|$7+xBPBoAk*?$M8lyr<=04M7yRhT z<*ZZcA!g74BjH!Hi1ZReTnuG1g5N>LPdizXuo^({ge<8s)j_#G(ICX6A^O8ATHXXOHbwYr{_iy=V_(8B-X>WTlkA<}Ph}kAV!9T5DUOKL#OcA(Q~5EzMbIzU*3I1E zm}coKFlMszAFD1l)gd&f zRVPExg|N<4L)1xhYCDT3(=-rHm)oM_?qQW*7%8---qUirslgr)K%U#%t7ER9??wp? z5q~?GE{{|ly9SH6*OH{A%CzLl0&1$pd96IqwE)cAA_b_P8A`U4I)CTTM?%c(>!@Mb z6~%|rg2#Brr%6dUkM>87st!(fF}(A{sWpSYMcc?A4)=el3i`x^ce5jU*3-| z|5dn$TSURFK%-pow<^{yVqq3a@}NXYwT;MnCo4;kl(h%V=Rvxx68T{#| zTyaBygMQ8$wj@gpOAa)pbS-+ky{Tix{syKa0q-@FrrY6VfLt;$KU;5wYod7`_29QT z{mgC`LhQ$86b3j7b!e>!NeWW}y#7ax z&wLSO&p^{8y2*^{{(+;fM})ecDsmK)qSs43zn(Nk4s?knq%u>Xh~bGM0rKE=un5#; zK7>DD8I$E9BX$hJMH~dTN<6pTkyhVAEjV^J^CO+R4%!*M$rcVc$TfEC?%ev#cSt{w zh%qFd4B`~m7H>$p&My~-4N%T3BdMgvjS{&UdL)d8%B)9f%vv#jFXDLK5Mt1Mf(0rf zU~Jp>zkKY8Az+{3ncXYseT^WY!6NkKL^nV!)jU4{(9qRq=x}n7{6XVjlh^r}9C^+I*&;cO(ULvTX5e9N&?MFLGL~Gp=h< zV9%PUq#-%9?lzF_OA5R@n|6M%w?q7ZhKNFpo#v=;!CVyA-_&4VbbZv} zZ>dP-BxWl3S6a;|Oab#sT*Sq9pE4xzDNuN$EPETbB2;#NOMP}Y-%7ud4dU}8!T$q2 z44V-t7ya%@w|*J4PdY>-hTwR+yhK2KWkXdOLlikaXD+!Q(u=>1fbE88-IP6-wa1b- zKJB`U;ONt&u%Qb5236owo9A{l-))#JcxsDy8$dT}?gh#V9uLkrdc|HU{9Ue{tfiaF(vJ9{OWuvML(6rsDeB1L|K~ zB>1N!QUWu^E__5e>Dylw&QbPuz(Dd6n)rAGaA=k~{(ZD~$P z#P5Sj@isCIOe$tc!hL@Vn&5aeQ4pK7Cs>)eS}7b_3MEm|Zm`7I)lPR!kv{|r(9N5) zTg+q%NYLdePPr%YTZwY;zvFGdQ97LNufJ}qELUvaO7;(>oyNiu*D3|6pN_u?H02aW zi*WonepfB_2eR0JQ((;KA%k;&T2~LOo7&On_G}`pOBjtCeZZjE`r{G(eNUHNer8p; zo}GYbpTQF{8``;7t4Jyu>P+Rk*|hfhVp6{2RW~Xo zufigTSbyaC#A$vdneuxXJr6`#OiQ6B2FY_d9CDbp+FSXEsMuDV zQl?>mN{V_fc`yWPlRN3HPY#rJz3hwB(s5R?;7&3h0MQ1Cqc}8ueQkt=7MTpR;pWxb z6iC%DS)q8|_NAJ}_^2p}Zv@Ch3&U&7w06Gi)Uoye$(|Fc#r=vgqJ!^!$!76`q5HSl z<6-*(Ahblo;<9>NH9cw70*=c!EsA=)E_K3iAFEZ>f*Cf7OvA1F%6xV*%7}NC^F

-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
*-1n5`ZlJOZ;TMs|uW8y>a~ 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 literal 0 HcmV?d00001 diff --git a/studio-desktop/src/main/resources/studio.bat b/studio-desktop/src/main/resources/studio.bat new file mode 100755 index 000000000..f0b5a0a10 --- /dev/null +++ b/studio-desktop/src/main/resources/studio.bat @@ -0,0 +1,7 @@ +@echo off + + +set VERSION=${project.build.finalName} +set STUDIO_CP=".\lib\*;%VERSION%.jar;." + +java -cp "%STUDIO_CP%" -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI diff --git a/studio-desktop/src/main/resources/studio.sh b/studio-desktop/src/main/resources/studio.sh new file mode 100755 index 000000000..b7c9bb7f9 --- /dev/null +++ b/studio-desktop/src/main/resources/studio.sh @@ -0,0 +1,7 @@ +#/bin/bash + +APP_PATH=`dirname $0` +VERSION=studio-desktop-0.3.2-SNAPSHOT +STUDIO_CP=$APP_PATH/lib/*:$APP_PATH:$APP_PATH/$VERSION.jar + +java -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI \ No newline at end of file From c82825d5c827b1f5f786ad9d845caefb51960788 Mon Sep 17 00:00:00 2001 From: Horfee Date: Thu, 13 Apr 2023 15:26:05 +0200 Subject: [PATCH 04/21] small fixes --- .../libusb4java-1.3.0-darwin-aarch64.jar | Bin 0 -> 20499 bytes studio-desktop/src/main/assembly/dist.xml | 2 +- studio-desktop/src/main/java/studio/GUI.java | 322 +++++++++++++----- .../src/main/java/studio/JsonPackCell.java | 22 +- .../main/java/studio/database/JsonPack.java | 12 + .../main/java/studio/database/Library.java | 32 +- .../localization/Translation.properties | 2 + .../localization/Translation_fr_FR.properties | 2 + 8 files changed, 292 insertions(+), 102 deletions(-) create mode 100644 studio-desktop/libusb4java-1.3.0-darwin-aarch64.jar diff --git a/studio-desktop/libusb4java-1.3.0-darwin-aarch64.jar b/studio-desktop/libusb4java-1.3.0-darwin-aarch64.jar new file mode 100644 index 0000000000000000000000000000000000000000..24462c1e2cb2d2d5b4fcaf19a66a6c5bbacee114 GIT binary patch literal 20499 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

+kW1+|qqL?5U;Kt5Msv4L&^vV3 z`U_#f{Vs67!Meh**47e_RbIjH%HZ7`ji*Bx{`!x2y{T}dv;JhbmH)fhk)AJsF@n&_ z#a9(wE)LDMsHt}-&%W-ZFhXp%ri;IC1of@kb`8;YkJUM!7;|y%6=O(^P52k_gPge; zQ7L}!h2^mh84B(yZYe$IsMSnN{k}EoO1tyP7-k>pqaTL;Ipa->EZKAnMRBEQUlu;D z;@rS;`>)vgM!}hHBd^7VJ2H;a#^(USYs2JdQL~v{2c)lRw5o26Q|ZAvzddgJ(n@uz z?;sqvrbb&-8h0!1yYBGCHz23&QB)0`+0<0}K(IQRdw=hm%Im7_>d{SjcEQV2UQy?U zmoN5>CgVyKLNP(HmBGHNzE(CX?TmM}k|QDf-E>fJ&&_XLOO~q=&n9IG5i2U_cb!Tu zqdx}s`4}g2|=yEi}~boX;70fNN1AP)wFt+DrD&B{rO< zR$d-zkjoa6KoxIYBwWe3gNr676|A|yV_$*usst}>2P3CSI!OHKcDP2V=l5WqV#?X} zP#jpuDpwIbUX$AZZ$r>+L@ox&NKmfaHEu?|QqD_!sN8j>G+k{+);0 zfaQMFrcHl~{ueX%yF1vp4>)|lhjjw+IsIrtK literal 0 HcmV?d00001 diff --git a/studio-desktop/src/main/assembly/dist.xml b/studio-desktop/src/main/assembly/dist.xml index 0d0cab57b..f4d7d86cb 100644 --- a/studio-desktop/src/main/assembly/dist.xml +++ b/studio-desktop/src/main/assembly/dist.xml @@ -8,7 +8,7 @@ dist - jar + zip diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index e7f0df0f7..d947fc970 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -80,6 +80,7 @@ import studio.driver.model.fs.FsStoryPackInfos; import studio.driver.model.raw.RawDeviceInfos; import studio.driver.model.raw.RawStoryPackInfos; +import studio.driver.raw.LibUsbMassStorageHelper; import studio.driver.raw.RawStoryTellerAsyncDriver; import java.awt.Toolkit; @@ -124,12 +125,17 @@ public class GUI { private JButton btnRefreshLibrary; private ResourceBundle localization; private Label lblTransferingPack; - + private boolean mustCancel = false; + private GridBagLayout statusLayout; + private JPanel statusPanel; + private JButton btnCancel; /** * Launch the application. */ public static void main(String[] args) { + + EventQueue.invokeLater(new Runnable() { public void run() { try { @@ -275,8 +281,8 @@ public void onDevicePlugged(Device device) { uUIDTextBox.setText(deviceInfos.getUuid().toString()); //uUIDTextBox.setText(deviceInfos.getUuid().toString()); firmwareTextBox.setText(deviceInfos.getFirmwareMajor() + "." + deviceInfos.getFirmwareMinor()); - totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getSdCardSizeInSectors())); - usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInSectors())); + totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getSdCardSizeInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); btnDownloadPackages.setEnabled(false); btnValidate.setEnabled(false); @@ -317,6 +323,24 @@ public void onDevicePlugged(Device device) { // }); } + private void refreshFreeSpaceOnDevice() { + try { + if (fsDriverUsed) { + FsDeviceInfos deviceInfos; + deviceInfos = fsDriver.getDeviceInfos().get(); + + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInBytes())); + + } else if (rawDriverUsed) { + RawDeviceInfos deviceInfos = rawDriver.getDeviceInfos().get(); + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); + + } + } catch (InterruptedException | ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } /** @@ -450,46 +474,44 @@ private void initialize() { panel_1.add(usedSizeTextBox, gbc_usedSizeTextBox); usedSizeTextBox.setColumns(10); - JPanel panel_3 = new JPanel(); - panel.add(panel_3, BorderLayout.SOUTH); - GridBagLayout gbl_panel_3 = new GridBagLayout(); - gbl_panel_3.columnWidths = new int[] {0, 0, 0, 0}; - gbl_panel_3.rowHeights = new int[] {0}; - gbl_panel_3.columnWeights = new double[]{0.0, 1.0, 0.0, 1.0}; - gbl_panel_3.rowWeights = new double[]{0.0}; - panel_3.setLayout(gbl_panel_3); + statusPanel = new JPanel(); + panel.add(statusPanel, BorderLayout.SOUTH); + statusLayout = new GridBagLayout(); + statusLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 1.0}; + statusPanel.setLayout(statusLayout); - lblTransferingPack = new Label();//"Transfering pack {}"); + lblTransferingPack = new Label(""); GridBagConstraints gbc_lblTransferingPack = new GridBagConstraints(); - gbc_lblTransferingPack.anchor = GridBagConstraints.WEST; - gbc_lblTransferingPack.insets = new Insets(5, 5, 5, 5); - gbc_lblTransferingPack.gridx = 0; + gbc_lblTransferingPack.fill = GridBagConstraints.HORIZONTAL; + gbc_lblTransferingPack.insets = new Insets(0, 5, 0, 5); gbc_lblTransferingPack.gridy = 0; - panel_3.add(lblTransferingPack, gbc_lblTransferingPack); + gbc_lblTransferingPack.gridx = 0; + statusPanel.add(lblTransferingPack, gbc_lblTransferingPack); installUninstallProgressBar = new JProgressBar(); GridBagConstraints gbc_installUninstallProgressBar = new GridBagConstraints(); gbc_installUninstallProgressBar.fill = GridBagConstraints.HORIZONTAL; - gbc_installUninstallProgressBar.insets = new Insets(5, 0, 5, 5); + gbc_installUninstallProgressBar.insets = new Insets(0, 0, 0, 5); gbc_installUninstallProgressBar.gridx = 1; gbc_installUninstallProgressBar.gridy = 0; - panel_3.add(installUninstallProgressBar, gbc_installUninstallProgressBar); + statusPanel.add(installUninstallProgressBar, gbc_installUninstallProgressBar); - Label lblProgress = new Label(localization.getString("Transfer.globalProgress"));//"Progress"); + Label lblProgress = new Label(localization.getString("Transfer.globalProgress")); GridBagConstraints gbc_lblProgress = new GridBagConstraints(); - gbc_lblProgress.anchor = GridBagConstraints.WEST; - gbc_lblProgress.insets = new Insets(5, 0, 5, 5); + gbc_lblProgress.fill = GridBagConstraints.HORIZONTAL; + gbc_lblProgress.insets = new Insets(0, 0, 0, 5); gbc_lblProgress.gridx = 2; gbc_lblProgress.gridy = 0; - panel_3.add(lblProgress, gbc_lblProgress); + statusPanel.add(lblProgress, gbc_lblProgress); globalProgressBar = new JProgressBar(); + globalProgressBar.setStringPainted(false); GridBagConstraints gbc_globalProgressBar = new GridBagConstraints(); gbc_globalProgressBar.fill = GridBagConstraints.HORIZONTAL; - gbc_globalProgressBar.insets = new Insets(5, 0, 5, 5); + gbc_globalProgressBar.insets = new Insets(0, 0, 0, 5); gbc_globalProgressBar.gridx = 3; gbc_globalProgressBar.gridy = 0; - panel_3.add(globalProgressBar, gbc_globalProgressBar); + statusPanel.add(globalProgressBar, gbc_globalProgressBar); devicePacksModel = new DefaultListModel(); @@ -691,7 +713,7 @@ public boolean importData(TransferHandler.TransferSupport support) { JPanel panel_4 = new JPanel(); panel_2.add(panel_4, BorderLayout.SOUTH); GridBagLayout gbl_panel_4 = new GridBagLayout(); - gbl_panel_4.columnWeights = new double[]{0.0, 0.0, 0.0, 1.0}; + gbl_panel_4.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 1.0}; gbl_panel_4.rowWeights = new double[]{0.0}; panel_4.setLayout(gbl_panel_4); @@ -699,62 +721,106 @@ public boolean importData(TransferHandler.TransferSupport support) { btnDownloadPackages.setEnabled(false); GridBagConstraints gbc_btnDownloadPackages = new GridBagConstraints(); gbc_btnDownloadPackages.anchor = GridBagConstraints.NORTHWEST; - gbc_btnDownloadPackages.insets = new Insets(0, 0, 0, 5); + gbc_btnDownloadPackages.insets = new Insets(0, 0, 5, 5); gbc_btnDownloadPackages.gridx = 0; gbc_btnDownloadPackages.gridy = 0; panel_4.add(btnDownloadPackages, gbc_btnDownloadPackages); btnDownloadPackages.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - int[] selected = devicePacksList.getSelectedIndices(); - if ( selected.length == 0 ) { - selected = IntStream.range(0, devicePacksModel.getSize()).toArray(); - } - Arrays.stream(selected).boxed().map( (i) -> devicePacksModel.get(i)).forEach( (pack) -> { - if ( fsDriverUsed ) { - fsDriver.downloadPack(pack.getUuid(), library.getLibraryPath(), new TransferProgressListener() { - - @Override - public void onProgress(TransferStatus status) { - installUninstallProgressBar.setMinimum(0); - installUninstallProgressBar.setMaximum(status.getTotal()); - installUninstallProgressBar.setValue(status.getTransferred()); + + btnRefresh.setEnabled(false); + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnCancel.setEnabled(true); + + + CompletableFuture.runAsync( () -> { + int[] selected = devicePacksList.getSelectedIndices(); + if ( selected.length == 0 ) { + selected = IntStream.range(0, devicePacksModel.getSize()).toArray(); + } + globalProgressBar.setString("0/" + selected.length); + globalProgressBar.setStringPainted(true); + globalProgressBar.setMaximum(selected.length); + + Arrays.stream(selected).boxed().map( (i) -> devicePacksModel.get(i)).forEach( (pack) -> { + boolean mustCancelLocal = false; + synchronized(this) { + mustCancelLocal = mustCancel; + } + if ( fsDriverUsed && !mustCancelLocal) { + try { - } - - @Override - public void onComplete(TransferStatus status) { - installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + JsonPack jsonPack = library.getPackForUUID(pack.getUuid()).get(); + String packTitle = jsonPack.getTitle(); + if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); + fsDriver.downloadPack(pack.getUuid(), library.getLibraryPath(), new TransferProgressListener() { + + @Override + public void onProgress(TransferStatus status) { + installUninstallProgressBar.setMinimum(0); + installUninstallProgressBar.setMaximum(status.getTotal()); + installUninstallProgressBar.setValue(status.getTransferred()); + + } + + @Override + public void onComplete(TransferStatus status) { + } + }).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } - }); - } else if ( rawDriverUsed ) { - try { - rawDriver.downloadPack(pack.getUuid(), Files.newOutputStream(Paths.get(library.getLibraryPath(), pack.getUuid() + ".pack")), new TransferProgressListener() { + } else if ( rawDriverUsed && !mustCancelLocal) { + try { + JsonPack jsonPack = library.getPackForUUID(pack.getUuid()).get(); + String packTitle = jsonPack.getTitle(); + if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); - @Override - public void onProgress(TransferStatus status) { - installUninstallProgressBar.setMinimum(0); - installUninstallProgressBar.setMaximum(status.getTotal()); - installUninstallProgressBar.setValue(status.getTransferred()); + rawDriver.downloadPack(pack.getUuid(), Files.newOutputStream(Paths.get(library.getLibraryPath(), pack.getUuid() + ".pack")), new TransferProgressListener() { - } - - @Override - public void onComplete(TransferStatus status) { - installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + @Override + public void onProgress(TransferStatus status) { + installUninstallProgressBar.setMinimum(0); + installUninstallProgressBar.setMaximum(status.getTotal()); + installUninstallProgressBar.setValue(status.getTransferred()); + } - } - }); - } catch (IOException e1) { - e1.printStackTrace(); + @Override + public void onComplete(TransferStatus status) { + } + }).get(); + } catch (IOException | InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + } } + }); + + synchronized (this) { + mustCancel = false; } + + lblTransferingPack.setText(""); + installUninstallProgressBar.setValue(0); + globalProgressBar.setValue(0); + globalProgressBar.setStringPainted(false); + btnRefresh.setEnabled(true); + btnDownloadPackages.setEnabled(true); + btnValidate.setEnabled(true); + btnCancel.setEnabled(false); }); -// for(int i : selected) { -// if ( fsDriverUsed ) { -// fsDriver.downloadPack(null, null, null) -// } -// } + } }); @@ -762,12 +828,17 @@ public void onComplete(TransferStatus status) { btnValidate.setEnabled(false); GridBagConstraints gbc_btnValidate = new GridBagConstraints(); gbc_btnValidate.anchor = GridBagConstraints.NORTHWEST; - gbc_btnValidate.insets = new Insets(0, 0, 0, 5); + gbc_btnValidate.insets = new Insets(0, 0, 5, 5); gbc_btnValidate.gridx = 1; gbc_btnValidate.gridy = 0; panel_4.add(btnValidate, gbc_btnValidate); btnValidate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { + btnRefresh.setEnabled(false); + btnValidate.setEnabled(false); + btnDownloadPackages.setEnabled(false); + btnCancel.setEnabled(true); + loadPacksFromDevice().thenAcceptAsync( (packs) -> { try { @@ -783,33 +854,58 @@ public void actionPerformed(ActionEvent e) { toInstall.removeAll(uuids); int nbSteps = toUninstall.size() + toInstall.size() + 1; + boolean mustCancelLocal = false; globalProgressBar.setMinimum(0); globalProgressBar.setMaximum(nbSteps); globalProgressBar.setValue(0); - if ( fsDriverUsed ) { + globalProgressBar.setString("0/" + nbSteps); + globalProgressBar.setStringPainted(true); + + synchronized(this) { + mustCancelLocal = mustCancel; + } + if ( fsDriverUsed && !mustCancelLocal ) { toUninstall.forEach( (pack) -> { try { - String packTitle = library.getPackForUUID(pack).get().getTitle(); + synchronized(this) { + if ( mustCancel ) return; + } + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); lblTransferingPack.setText(localization.getString("Transfering.deletingpack").replace("{}", packTitle)); + statusPanel.updateUI(); fsDriver.deletePack(pack).get(); + + refreshFreeSpaceOnDevice(); } catch (InterruptedException | ExecutionException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } }); - } else if ( rawDriverUsed ) { + } else if ( rawDriverUsed && !mustCancelLocal ) { toUninstall.forEach( (pack) -> { try { - String packTitle = library.getPackForUUID(pack).get().getTitle(); + synchronized(this) { + if ( mustCancel ) return; + } + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); lblTransferingPack.setText(localization.getString("Transfering.deletingpack").replace("{}", packTitle)); + statusPanel.updateUI(); rawDriver.deletePack(pack).get(); + + refreshFreeSpaceOnDevice(); } catch (InterruptedException | ExecutionException e1) { e1.printStackTrace(); } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } }); } @@ -831,42 +927,68 @@ public void onComplete(TransferStatus status) { } }; - if ( fsDriverUsed ) { + synchronized(this) { + mustCancelLocal = mustCancel; + } + if ( fsDriverUsed && !mustCancelLocal ) { toInstall.forEach( (pack) -> { try { - String packTitle = library.getPackForUUID(pack).get().getTitle(); + synchronized(this) { + if ( mustCancel ) return; + } + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); + statusPanel.updateUI(); fsDriver.uploadPack(pack, library.getFolderForUUID(pack), progressListener).get(); + + refreshFreeSpaceOnDevice(); } catch (InterruptedException | ExecutionException e1) { e1.printStackTrace(); } finally { globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } }); - } else if ( rawDriverUsed ) { + } else if ( rawDriverUsed && !mustCancelLocal) { toInstall.forEach( (pack) -> { try { - // TODO : getAckInputStream - String packTitle = library.getPackForUUID(pack).get().getTitle(); + synchronized(this) { + if ( mustCancel ) return; + } + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); + statusPanel.updateUI(); rawDriver.uploadPack(null, 0, progressListener).get(); + + refreshFreeSpaceOnDevice(); } catch (InterruptedException | ExecutionException e1) { e1.printStackTrace(); } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } }); } // Reorder packs - if ( fsDriverUsed ) { + synchronized(this) { + mustCancelLocal = mustCancel; + } + if ( fsDriverUsed && !mustCancelLocal) { try { lblTransferingPack.setText(localization.getString("Transfering.reordering")); + statusPanel.updateUI(); + fsDriver.reorderPacks(uuidsInList).get(); } catch (InterruptedException | ExecutionException e1) { e1.printStackTrace(); } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } } else { try { @@ -875,6 +997,7 @@ public void onComplete(TransferStatus status) { e1.printStackTrace(); } finally { globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } } @@ -883,6 +1006,19 @@ public void onComplete(TransferStatus status) { e2.printStackTrace(); } + synchronized(this) { + mustCancel = false; + } + btnRefresh.setEnabled(true); + btnValidate.setEnabled(true); + btnCancel.setEnabled(false); + btnDownloadPackages.setEnabled(true); + lblTransferingPack.setText(localization.getString("Transfering.done")); + + installUninstallProgressBar.setValue(0); + globalProgressBar.setValue(0); + globalProgressBar.setString(null); + statusPanel.updateUI(); }); } }); @@ -891,7 +1027,7 @@ public void onComplete(TransferStatus status) { btnRefresh.setEnabled(false); GridBagConstraints gbc_btnRefersh = new GridBagConstraints(); gbc_btnRefersh.anchor = GridBagConstraints.NORTHWEST; - gbc_btnRefersh.insets = new Insets(0, 0, 0, 5); + gbc_btnRefersh.insets = new Insets(0, 0, 5, 5); gbc_btnRefersh.gridx = 2; gbc_btnRefersh.gridy = 0; panel_4.add(btnRefresh, gbc_btnRefersh); @@ -914,10 +1050,28 @@ public void actionPerformed(ActionEvent e) { } }); + btnCancel = new JButton(localization.getString("Device.cancel")); + + btnCancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + synchronized(this) { + mustCancel = true; + } + btnCancel.setEnabled(false); + } + }); + btnCancel.setEnabled(false); + GridBagConstraints gbc_btnCancel = new GridBagConstraints(); + gbc_btnCancel.insets = new Insets(0, 0, 5, 5); + gbc_btnCancel.gridx = 3; + gbc_btnCancel.gridy = 0; + panel_4.add(btnCancel, gbc_btnCancel); + devicePacksSummaryLabel = new JLabel("-/-"); GridBagConstraints gbc_devicePacksSummaryLabel = new GridBagConstraints(); + gbc_devicePacksSummaryLabel.insets = new Insets(0, 0, 5, 0); gbc_devicePacksSummaryLabel.anchor = GridBagConstraints.EAST; - gbc_devicePacksSummaryLabel.gridx = 3; + gbc_devicePacksSummaryLabel.gridx = 4; gbc_devicePacksSummaryLabel.gridy = 0; panel_4.add(devicePacksSummaryLabel, gbc_devicePacksSummaryLabel); diff --git a/studio-desktop/src/main/java/studio/JsonPackCell.java b/studio-desktop/src/main/java/studio/JsonPackCell.java index c02badeac..94d943ae5 100644 --- a/studio-desktop/src/main/java/studio/JsonPackCell.java +++ b/studio-desktop/src/main/java/studio/JsonPackCell.java @@ -19,6 +19,8 @@ import javax.swing.border.Border; import javax.swing.plaf.UIResource; +import org.apache.commons.io.FileUtils; + import studio.database.JsonPack; import studio.database.LocalizedInfos; @@ -42,7 +44,7 @@ class JsonPackCell implements ListCellRenderer, UIResource { private JPanel initialize() { JPanel res = new JPanel(); GridBagLayout gridBagLayout = new GridBagLayout(); - gridBagLayout.columnWeights = new double[]{0.0, 1.0}; + gridBagLayout.columnWeights = new double[]{0.0, 1.0, 1.0}; res.setLayout(gridBagLayout); JLabel icon = new JLabel(); @@ -50,7 +52,7 @@ private JPanel initialize() { icon.setPreferredSize(new Dimension(64, 64)); GridBagConstraints gbc_icon = new GridBagConstraints(); gbc_icon.gridheight = 3; - gbc_icon.insets = new Insets(5, 5, 5, 5); + gbc_icon.insets = new Insets(5, 5, 0, 5); gbc_icon.gridx = 0; gbc_icon.gridy = 0; res.add(icon, gbc_icon); @@ -81,13 +83,23 @@ private JPanel initialize() { ageLabel.setName("age"); GridBagConstraints gbc_ageLabel = new GridBagConstraints(); gbc_ageLabel.anchor = GridBagConstraints.WEST; - gbc_ageLabel.insets = new Insets(0 , 5, 5, 5); + gbc_ageLabel.insets = new Insets(0, 5, 0, 5); gbc_ageLabel.gridx = 1; gbc_ageLabel.gridy = 2; res.add(ageLabel, gbc_ageLabel); res.setPreferredSize(new Dimension(412, 64)); + JLabel sizeLabel = new JLabel(); + sizeLabel.setText("size"); + sizeLabel.setName("size"); + GridBagConstraints gbc_sizeLabel = new GridBagConstraints(); + gbc_sizeLabel.anchor = GridBagConstraints.EAST; + gbc_sizeLabel.gridx = 2; + gbc_sizeLabel.gridy = 2; + gbc_sizeLabel.insets = new Insets(0, 0, 0, 5); + res.add(sizeLabel, gbc_sizeLabel); + return res; } @@ -178,6 +190,10 @@ public Component getListCellRendererComponent(JList list, Js String strAge = value.getAgeMax() == -1 ? "From " + value.getAgeMin() + " years": "From " + value.getAgeMin() + " to " + value.getAgeMax() + " years"; ((JLabel)c).setText(strAge); }); + components.stream().filter( (c) -> "size".equals(c.getName())).findFirst().ifPresent( ( c) -> { + String strAge = FileUtils.byteCountToDisplaySize(FileUtils.ONE_KB * value.getSize()); + ((JLabel)c).setText(strAge); + }); //subTitle.setText(strSubTitle); diff --git a/studio-desktop/src/main/java/studio/database/JsonPack.java b/studio-desktop/src/main/java/studio/database/JsonPack.java index 76f3beaa9..55929e13f 100644 --- a/studio-desktop/src/main/java/studio/database/JsonPack.java +++ b/studio-desktop/src/main/java/studio/database/JsonPack.java @@ -58,7 +58,19 @@ public class JsonPack { @SerializedName("localized_infos") private Map localizedInfos; + @SerializedName("size") + private long size; + + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + public String getSlug() { return slug; } diff --git a/studio-desktop/src/main/java/studio/database/Library.java b/studio-desktop/src/main/java/studio/database/Library.java index c9832c734..8c83511f6 100644 --- a/studio-desktop/src/main/java/studio/database/Library.java +++ b/studio-desktop/src/main/java/studio/database/Library.java @@ -37,14 +37,30 @@ public class Library { public static final String TOKEN_URL = "https://server-auth-prod.lunii.com/guest/create"; public static final String DATABASE_URL = "https://server-data-prod.lunii.com/v2/packs"; - public static final String RESOURCE_URL = "https://storage.googleapis.com/lunii-data-prod"; + public static final String RESOURCE_URL = "https://storage.googleapis.com/lunii-data-prod"; private JsonResponse officalPacksDatabase; private static volatile Library instance; + private static Gson gson; + private String libraryPath; + static { + GsonBuilder builder = new GsonBuilder(); + builder.registerTypeAdapter(Date.class, new JsonDeserializer() { + + @Override + public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return new Date(json.getAsLong()); + } + + }); + + gson = builder.create(); + } public static Library getInstance(String path) { if (instance != null && instance.libraryPath.equals(path)) { return instance; @@ -177,21 +193,9 @@ public CompletableFuture fetchFromServer() { URLConnection connection = getDatabase.openConnection(); connection.addRequestProperty("X-AUTH-TOKEN", token); - GsonBuilder builder = new GsonBuilder(); - builder.registerTypeAdapter(Date.class, new JsonDeserializer() { - - @Override - public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) - throws JsonParseException { - return new Date(json.getAsLong()); - } - - }); - - Gson gson = builder.create(); officalPacksDatabase = gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonResponse.class); - System.out.println(officalPacksDatabase.getPacks().stream().map( (p) -> p.getUuid()).toList()); + //System.out.println(officalPacksDatabase.getPacks().stream().map( (p) -> p.getUuid()).toList()); } catch(NullPointerException e) { e.printStackTrace(); } catch (MalformedURLException e) { diff --git a/studio-desktop/src/main/java/studio/localization/Translation.properties b/studio-desktop/src/main/java/studio/localization/Translation.properties index 225bb705d..4cefa19c6 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation.properties @@ -9,9 +9,11 @@ Device.download=Download Device.list=Device Device.validate=Commit Device.refresh=Refresh +Device.cancel=Cancel Transfering.transferringpack=Transferring pack {} Transfering.deletingpack=Deleting pack {} Transfering.reordering=Ordering packs +Transfering.done=Done Transfer.globalProgress=Progress Library.list=List Library.refresh=Refresh library diff --git a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties index d297ba522..301c4c91f 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties @@ -9,9 +9,11 @@ Device.download=T Device.list=Boite lunii Device.validate=Valider Device.refresh=Rafraichir +Device.cancel=Annuler Transfering.transferringpack=Transfert du pack {} Transfering.deletingpack=Suppression du pack {} Transfering.reordering=Tri des packs +Transfering.done=Terminé Transfer.globalProgress=Progression Library.list=Liste Library.refresh=Rafraichir la librairie From fa10d99311a06301f7cb885ec87d0245a4d0d013 Mon Sep 17 00:00:00 2001 From: Horfee Date: Fri, 16 Jun 2023 14:12:26 +0200 Subject: [PATCH 05/21] Support for unofficials packs and general fixes. --- .gitignore | 6 +- .../core/v1/writer/fs/FsStoryPackWriter.java | 3 +- .../studio/driver/LibUsbDetectionHelper.java | 6 +- .../driver/fs/FsStoryTellerAsyncDriver.java | 103 +- studio-desktop/src/main/java/studio/GUI.java | 1768 +++++++++-------- .../src/main/java/studio/JsonPackCell.java | 62 +- .../java/studio/PlaceholderTextField.java | 41 + .../main/java/studio/database/JsonPack.java | 19 +- .../main/java/studio/database/Library.java | 219 +- .../java/studio/database/LocalizedInfos.java | 2 +- .../localization/Translation.properties | 8 +- .../localization/Translation_fr_FR.properties | 8 +- studio-desktop/src/main/resources/studio.sh | 2 +- 13 files changed, 1337 insertions(+), 910 deletions(-) create mode 100644 studio-desktop/src/main/java/studio/PlaceholderTextField.java diff --git a/.gitignore b/.gitignore index 36071c50d..16e4dcc8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,8 @@ .idea *.iml *node_modules -*target \ No newline at end of file +*target +.project +.settings +.classpath +*.log \ No newline at end of file diff --git a/core/src/main/java/studio/core/v1/writer/fs/FsStoryPackWriter.java b/core/src/main/java/studio/core/v1/writer/fs/FsStoryPackWriter.java index b6ea46d89..5ce32f455 100644 --- a/core/src/main/java/studio/core/v1/writer/fs/FsStoryPackWriter.java +++ b/core/src/main/java/studio/core/v1/writer/fs/FsStoryPackWriter.java @@ -45,7 +45,8 @@ public class FsStoryPackWriter { public Path write(StoryPack pack, Path outputFolder) throws Exception { // Create pack folder: last 8 digits of uuid - File packFolder = new File(outputFolder.toFile(), transformUuid(UUID.fromString(pack.getUuid()))); +// File packFolder = new File(outputFolder.toFile(), transformUuid(UUID.fromString(pack.getUuid()))); + File packFolder = outputFolder.toFile(); packFolder.mkdirs(); // Write night mode diff --git a/driver/src/main/java/studio/driver/LibUsbDetectionHelper.java b/driver/src/main/java/studio/driver/LibUsbDetectionHelper.java index 61748fb48..b3c2c665f 100644 --- a/driver/src/main/java/studio/driver/LibUsbDetectionHelper.java +++ b/driver/src/main/java/studio/driver/LibUsbDetectionHelper.java @@ -98,7 +98,11 @@ public static void initializeLibUsb(DeviceVersion deviceVersion, DeviceHotplugEv } } LOGGER.info("Exiting libusb..."); - LibUsb.exit(context); + + try { + LibUsb.exit(context); + } catch(IllegalStateException e) { + } }) ); } diff --git a/driver/src/main/java/studio/driver/fs/FsStoryTellerAsyncDriver.java b/driver/src/main/java/studio/driver/fs/FsStoryTellerAsyncDriver.java index 3517ff6f4..e106d1387 100644 --- a/driver/src/main/java/studio/driver/fs/FsStoryTellerAsyncDriver.java +++ b/driver/src/main/java/studio/driver/fs/FsStoryTellerAsyncDriver.java @@ -50,63 +50,72 @@ public class FsStoryTellerAsyncDriver { private List listeners = new ArrayList<>(); - public FsStoryTellerAsyncDriver() { - // Initialize libusb, handle and propagate hotplug events - LOGGER.fine("Registering hotplug listener"); - LibUsbDetectionHelper.initializeLibUsb(DeviceVersion.DEVICE_VERSION_2, new DeviceHotplugEventListener() { - @Override - public void onDevicePlugged(Device device) { - // Wait for a partition to be mounted which contains the .md file - LOGGER.fine("Waiting for device partition..."); - for (int i = 0; i < FS_MOUNTPOINT_RETRY && partitionMountPoint==null; i++) { - try { - Thread.sleep(FS_MOUNTPOINT_POLL_DELAY); - DeviceUtils.listMountPoints().forEach(path -> { - LOGGER.finest("Looking for .md file on mount point / drive: " + path); - File mdFile = new File(path, DEVICE_METADATA_FILENAME); - if (mdFile.exists()) { - partitionMountPoint = path; - LOGGER.info("FS device partition located: " + partitionMountPoint); - } - }); - } catch (InterruptedException e) { - LOGGER.log(Level.SEVERE, "Failed to locate device partition", e); - } + private boolean simulating = false; + public FsStoryTellerAsyncDriver(boolean simulating) { + this(); + this.simulating = simulating; + } + + + private DeviceHotplugEventListener defaultListener = new DeviceHotplugEventListener() { + @Override + public void onDevicePlugged(Device device) { + // Wait for a partition to be mounted which contains the .md file + LOGGER.fine("Waiting for device partition..."); + for (int i = 0; i < FS_MOUNTPOINT_RETRY && partitionMountPoint==null; i++) { + try { + Thread.sleep(FS_MOUNTPOINT_POLL_DELAY); + DeviceUtils.listMountPoints().forEach(path -> { + LOGGER.finest("Looking for .md file on mount point / drive: " + path); + File mdFile = new File(path, DEVICE_METADATA_FILENAME); + if (mdFile.exists()) { + partitionMountPoint = path; + LOGGER.info("FS device partition located: " + partitionMountPoint); } + }); + } catch (InterruptedException e) { + LOGGER.log(Level.SEVERE, "Failed to locate device partition", e); + } + } - if (partitionMountPoint == null) { - throw new StoryTellerException("Could not locate device partition"); - } + if (partitionMountPoint == null) { + throw new StoryTellerException("Could not locate device partition"); + } - // Update device reference - FsStoryTellerAsyncDriver.this.device = device; - // Notify listeners - FsStoryTellerAsyncDriver.this.listeners.forEach(listener -> listener.onDevicePlugged(device)); - } + // Update device reference + FsStoryTellerAsyncDriver.this.device = device; + // Notify listeners + FsStoryTellerAsyncDriver.this.listeners.forEach(listener -> listener.onDevicePlugged(device)); + } - @Override - public void onDeviceUnplugged(Device device) { - // Update device reference - FsStoryTellerAsyncDriver.this.device = null; - FsStoryTellerAsyncDriver.this.partitionMountPoint = null; - // Notify listeners - FsStoryTellerAsyncDriver.this.listeners.forEach(listener -> listener.onDeviceUnplugged(device)); - } - } - ); + @Override + public void onDeviceUnplugged(Device device) { + // Update device reference + FsStoryTellerAsyncDriver.this.device = null; + FsStoryTellerAsyncDriver.this.partitionMountPoint = null; + // Notify listeners + FsStoryTellerAsyncDriver.this.listeners.forEach(listener -> listener.onDeviceUnplugged(device)); + } + }; + + public FsStoryTellerAsyncDriver() { + // Initialize libusb, handle and propagate hotplug events + LOGGER.fine("Registering hotplug listener"); + LibUsbDetectionHelper.initializeLibUsb(DeviceVersion.DEVICE_VERSION_2, defaultListener); } public void registerDeviceListener(DeviceHotplugEventListener listener) { this.listeners.add(listener); - if (this.device != null) { + if (this.device != null || this.simulating) { + this.defaultListener.onDevicePlugged(null); listener.onDevicePlugged(this.device); } } public CompletableFuture getDeviceInfos() { - if (this.device == null || this.partitionMountPoint == null) { + if (!simulating && (this.device == null || this.partitionMountPoint == null)) { return CompletableFuture.failedFuture(new StoryTellerException("No device plugged")); } FsDeviceInfos infos = new FsDeviceInfos(); @@ -182,7 +191,7 @@ private long readBigEndianLong(FileInputStream fis) throws IOException { public CompletableFuture> getPacksList() { - if (this.device == null || this.partitionMountPoint == null) { + if (!simulating && (this.device == null || this.partitionMountPoint == null)) { return CompletableFuture.failedFuture(new StoryTellerException("No device plugged")); } @@ -255,7 +264,7 @@ private CompletableFuture> readPackIndex() { public CompletableFuture reorderPacks(List uuids) { - if (this.device == null || this.partitionMountPoint == null) { + if (!simulating && (this.device == null || this.partitionMountPoint == null)) { return CompletableFuture.failedFuture(new StoryTellerException("No device plugged")); } @@ -278,7 +287,7 @@ public CompletableFuture reorderPacks(List uuids) { } public CompletableFuture deletePack(String uuid) { - if (this.device == null || this.partitionMountPoint == null) { + if (!simulating && (this.device == null || this.partitionMountPoint == null)) { return CompletableFuture.failedFuture(new StoryTellerException("No device plugged")); } @@ -343,7 +352,7 @@ private CompletableFuture writePackIndex(List packUUIDs) { public CompletableFuture downloadPack(String uuid, String outputPath, TransferProgressListener listener) { - if (this.device == null || this.partitionMountPoint == null) { + if (!simulating && (this.device == null || this.partitionMountPoint == null)) { return CompletableFuture.failedFuture(new StoryTellerException("No device plugged")); } @@ -378,7 +387,7 @@ public CompletableFuture downloadPack(String uuid, String output } public CompletableFuture uploadPack(String uuid, String inputPath, TransferProgressListener listener) { - if (this.device == null || this.partitionMountPoint == null) { + if (!simulating && (this.device == null || this.partitionMountPoint == null)) { return CompletableFuture.failedFuture(new StoryTellerException("No device plugged")); } diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index d947fc970..a839b87d4 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -2,11 +2,14 @@ import java.awt.BorderLayout; import java.awt.Desktop; +import java.awt.Dimension; import java.awt.EventQueue; +import java.awt.Font; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Label; +import java.awt.Toolkit; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; @@ -23,6 +26,7 @@ import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; +import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -44,6 +48,7 @@ import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JButton; +import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; @@ -51,6 +56,7 @@ import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; @@ -58,7 +64,6 @@ import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; -import javax.swing.ScrollPaneConstants; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.border.TitledBorder; @@ -82,8 +87,6 @@ import studio.driver.model.raw.RawStoryPackInfos; import studio.driver.raw.LibUsbMassStorageHelper; import studio.driver.raw.RawStoryTellerAsyncDriver; -import java.awt.Toolkit; - public class GUI { @@ -97,14 +100,14 @@ public class GUI { // } // // } - + private JFrame frmLuniiTransfer; private JTextField serialNumberTextBox; private JTextField uUIDTextBox; private JTextField firmwareTextBox; private JTextField totalSizeTextBox; private JTextField usedSizeTextBox; - + private FsStoryTellerAsyncDriver fsDriver; private RawStoryTellerAsyncDriver rawDriver; private JList devicePacksList; @@ -112,7 +115,7 @@ public class GUI { private Library library; private DefaultListModel libraryPacksModel; private DefaultListModel devicePacksModel; - + private boolean fsDriverUsed = false; private boolean rawDriverUsed = false; private JProgressBar installUninstallProgressBar; @@ -129,21 +132,32 @@ public class GUI { private GridBagLayout statusLayout; private JPanel statusPanel; private JButton btnCancel; - + private JLabel libraryPathLabel; + private PlaceholderTextField librarySearchTextField; + private PlaceholderTextField deviceSearchTextField; + private JCheckBox displayOnlyNotOnDeviceCheckBox; + /** * Launch the application. */ public static void main(String[] args) { + + int javaVersion = Runtime.version().feature(); + if ( javaVersion < 14 ) { + JOptionPane.showMessageDialog(null, + "You must install and use Java version 14+ to run this program", + "Unsupported version of java", + JOptionPane.ERROR_MESSAGE); + + System.exit(1); + } EventQueue.invokeLater(new Runnable() { public void run() { try { - UIManager.setLookAndFeel( - UIManager.getSystemLookAndFeelClassName()); + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - - GUI window = new GUI(); window.frmLuniiTransfer.setVisible(true); } catch (Exception e) { @@ -158,35 +172,29 @@ public void run() { */ public GUI() { localization = ResourceBundle.getBundle("studio/localization/Translation", Locale.getDefault()); - + initialize(); initializeLunii(); - + } - + private CompletableFuture> loadPacksFromDevice() { - if ( fsDriverUsed ) { - return fsDriver.getPacksList().thenComposeAsync( (List packs) -> { - return library.fetchFromServer().thenApplyAsync( (Void v) -> { - List res = packs.stream() - .map( pack -> library.getPackForUUID( pack.getUuid().toString())) - .filter( Optional::isPresent ) - .map( Optional::get ) - .toList(); + if (fsDriverUsed) { + return fsDriver.getPacksList().thenComposeAsync((List packs) -> { + return library.loadDatabase().thenApplyAsync((Void v) -> { + List res = packs.stream().map(pack -> library.getPackForUUID(pack.getUuid().toString())) + .filter(Optional::isPresent).map(Optional::get).toList(); return res; }); }); - } else if ( rawDriverUsed ){ - return rawDriver.getPacksList().thenComposeAsync( (List packs) -> { - return library.fetchFromServer().thenApplyAsync( (Void v) -> { - List res = packs.stream() - .map( pack -> library.getPackForUUID( pack.getUuid().toString())) - .filter( Optional::isPresent ) - .map( Optional::get ) - .toList(); + } else if (rawDriverUsed) { + return rawDriver.getPacksList().thenComposeAsync((List packs) -> { + return library.loadDatabase().thenApplyAsync((Void v) -> { + List res = packs.stream().map(pack -> library.getPackForUUID(pack.getUuid().toString())) + .filter(Optional::isPresent).map(Optional::get).toList(); return res; }); - }); + }); } else { return CompletableFuture.supplyAsync(() -> new ArrayList()); } @@ -194,19 +202,20 @@ private CompletableFuture> loadPacksFromDevice() { private void initializeLunii() { + Locale l = Locale.getDefault(); library = Library.getInstance(System.getProperty("user.home")); - - library.getPacks().thenAcceptAsync( (List packs) -> { + + libraryPathLabel.setText("Path: " + library.getLibraryPath()); + library.getPacks().thenAcceptAsync((List packs) -> { libraryPacksModel.addAll(packs); btnRefreshLibrary.setEnabled(true); }); - - fsDriver = new FsStoryTellerAsyncDriver(); + fsDriver = new FsStoryTellerAsyncDriver(true); rawDriver = new RawStoryTellerAsyncDriver(); - + fsDriver.registerDeviceListener(new DeviceHotplugEventListener() { - + @Override public void onDeviceUnplugged(Device device) { devicePacksModel.clear(); @@ -215,12 +224,12 @@ public void onDeviceUnplugged(Device device) { firmwareTextBox.setText(""); totalSizeTextBox.setText(""); usedSizeTextBox.setText(""); - + btnDownloadPackages.setEnabled(false); btnValidate.setEnabled(false); btnRefresh.setEnabled(false); } - + @Override public void onDevicePlugged(Device device) { FsDeviceInfos deviceInfos; @@ -231,32 +240,31 @@ public void onDevicePlugged(Device device) { firmwareTextBox.setText(deviceInfos.getFirmwareMajor() + "." + deviceInfos.getFirmwareMinor()); totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getSdCardSizeInBytes())); usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInBytes())); - + btnDownloadPackages.setEnabled(false); btnValidate.setEnabled(false); btnRefresh.setEnabled(false); - + fsDriverUsed = true; rawDriverUsed = false; } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } - - - loadPacksFromDevice().thenAcceptAsync( (packs) -> { + + loadPacksFromDevice().thenAcceptAsync((packs) -> { devicePacksModel.clear(); devicePacksModel.addAll(packs); - + btnDownloadPackages.setEnabled(true); btnValidate.setEnabled(true); btnRefresh.setEnabled(true); }); - + } }); - + rawDriver.registerDeviceListener(new DeviceHotplugEventListener() { - + @Override public void onDeviceUnplugged(Device device) { devicePacksModel.clear(); @@ -265,13 +273,13 @@ public void onDeviceUnplugged(Device device) { firmwareTextBox.setText(""); totalSizeTextBox.setText(""); usedSizeTextBox.setText(""); - + btnDownloadPackages.setEnabled(false); btnValidate.setEnabled(false); btnRefresh.setEnabled(false); - + } - + @Override public void onDevicePlugged(Device device) { RawDeviceInfos deviceInfos; @@ -279,50 +287,40 @@ public void onDevicePlugged(Device device) { deviceInfos = rawDriver.getDeviceInfos().get(); serialNumberTextBox.setText(deviceInfos.getSerialNumber()); uUIDTextBox.setText(deviceInfos.getUuid().toString()); - //uUIDTextBox.setText(deviceInfos.getUuid().toString()); + // uUIDTextBox.setText(deviceInfos.getUuid().toString()); firmwareTextBox.setText(deviceInfos.getFirmwareMajor() + "." + deviceInfos.getFirmwareMinor()); - totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getSdCardSizeInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); - usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); - + totalSizeTextBox.setText(FileUtils.byteCountToDisplaySize( + deviceInfos.getSdCardSizeInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize( + deviceInfos.getUsedSpaceInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); + btnDownloadPackages.setEnabled(false); btnValidate.setEnabled(false); btnRefresh.setEnabled(false); - + fsDriverUsed = false; rawDriverUsed = true; - - + } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } - - loadPacksFromDevice().thenAcceptAsync( (packs) -> { + + loadPacksFromDevice().thenAcceptAsync((packs) -> { devicePacksModel.clear(); devicePacksModel.addAll(packs); - + btnDownloadPackages.setEnabled(true); btnValidate.setEnabled(true); btnRefresh.setEnabled(true); - + }); - - + } }); - -// CompletableFuture.runAsync(() -> { -// try { -// fsDriver.simulateDevicePlugged(); -// fsDriverUsed = true; -// rawDriverUsed = false; -// } catch (Exception e) { -// fsDriverUsed = false; -// rawDriverUsed = false; -// } -// }); + } - + private void refreshFreeSpaceOnDevice() { try { if (fsDriverUsed) { @@ -333,117 +331,116 @@ private void refreshFreeSpaceOnDevice() { } else if (rawDriverUsed) { RawDeviceInfos deviceInfos = rawDriver.getDeviceInfos().get(); - usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize(deviceInfos.getUsedSpaceInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); + usedSizeTextBox.setText(FileUtils.byteCountToDisplaySize( + deviceInfos.getUsedSpaceInSectors() * LibUsbMassStorageHelper.SECTOR_SIZE)); } } catch (InterruptedException | ExecutionException e) { - // TODO Auto-generated catch block e.printStackTrace(); } } - /** * Initialize the contents of the frame. */ private void initialize() { frmLuniiTransfer = new JFrame(); - frmLuniiTransfer.setIconImage(Toolkit.getDefaultToolkit().getImage(GUI.class.getResource("/lunii.png")));//.getDefaultToolkit().getImage("/Users/horfee/Developpement/studio.GoodOne/studio-desktop/src/main/resources/logolunii.jpeg")); + frmLuniiTransfer.setIconImage(Toolkit.getDefaultToolkit().getImage(GUI.class.getResource("/lunii.png")));// .getDefaultToolkit().getImage("/Users/horfee/Developpement/studio.GoodOne/studio-desktop/src/main/resources/logolunii.jpeg")); frmLuniiTransfer.setTitle(localization.getString("Frame.Title")); frmLuniiTransfer.setBounds(100, 100, 1024, 720); frmLuniiTransfer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frmLuniiTransfer.getContentPane().setLayout(new BoxLayout(frmLuniiTransfer.getContentPane(), BoxLayout.X_AXIS)); - + JPanel panel = new JPanel(); frmLuniiTransfer.getContentPane().add(panel); panel.setLayout(new BorderLayout(0, 0)); - - JPanel panel_1 = new JPanel(); - panel.add(panel_1, BorderLayout.NORTH); - GridBagLayout gbl_panel_1 = new GridBagLayout(); - gbl_panel_1.columnWidths = new int[] {0, 0, 0, 0}; - gbl_panel_1.rowHeights = new int[] {0, 0, 0, 0, 0, 0, 0}; - gbl_panel_1.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0}; - gbl_panel_1.rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE}; - panel_1.setLayout(gbl_panel_1); - + + JPanel informationPanel = new JPanel(); + panel.add(informationPanel, BorderLayout.NORTH); + GridBagLayout gbl_informationPanel = new GridBagLayout(); + gbl_informationPanel.columnWidths = new int[] { 0, 0, 0, 0 }; + gbl_informationPanel.rowHeights = new int[] { 0, 0, 0, 0, 0, 0, 0 }; + gbl_informationPanel.columnWeights = new double[] { 0.0, 1.0, 0.0, 1.0 }; + gbl_informationPanel.rowWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Double.MIN_VALUE }; + informationPanel.setLayout(gbl_informationPanel); + JLabel deviceInformationLabel = new JLabel(localization.getString("Device.Information")); GridBagConstraints gbc_deviceInformationLabel = new GridBagConstraints(); gbc_deviceInformationLabel.gridwidth = 4; gbc_deviceInformationLabel.fill = GridBagConstraints.HORIZONTAL; gbc_deviceInformationLabel.gridx = 0; gbc_deviceInformationLabel.gridy = 0; - gbc_deviceInformationLabel.insets = new Insets(5, 5, 5, 5); - panel_1.add(deviceInformationLabel, gbc_deviceInformationLabel); - - JLabel serialNumberLabel = new JLabel(localization.getString("Device.serialnum"));//"Serial number :"); + gbc_deviceInformationLabel.insets = new Insets(5, 5, 5, 0); + informationPanel.add(deviceInformationLabel, gbc_deviceInformationLabel); + + JLabel serialNumberLabel = new JLabel(localization.getString("Device.serialnum"));// "Serial number :"); GridBagConstraints gbc_serialNumberLabel = new GridBagConstraints(); gbc_serialNumberLabel.anchor = GridBagConstraints.EAST; gbc_serialNumberLabel.insets = new Insets(5, 5, 5, 5); gbc_serialNumberLabel.gridx = 0; gbc_serialNumberLabel.gridy = 1; - panel_1.add(serialNumberLabel, gbc_serialNumberLabel); - + informationPanel.add(serialNumberLabel, gbc_serialNumberLabel); + serialNumberTextBox = new JTextField(); serialNumberTextBox.setEditable(false); GridBagConstraints gbc_serialNumberTextBox = new GridBagConstraints(); gbc_serialNumberTextBox.weightx = 1.0; gbc_serialNumberTextBox.gridwidth = 3; - gbc_serialNumberTextBox.insets = new Insets(5, 0, 5, 5); + gbc_serialNumberTextBox.insets = new Insets(5, 0, 5, 0); gbc_serialNumberTextBox.fill = GridBagConstraints.HORIZONTAL; gbc_serialNumberTextBox.gridx = 1; gbc_serialNumberTextBox.gridy = 1; - panel_1.add(serialNumberTextBox, gbc_serialNumberTextBox); + informationPanel.add(serialNumberTextBox, gbc_serialNumberTextBox); serialNumberTextBox.setColumns(10); - - JLabel uUIDLabel = new JLabel(localization.getString("Device.UUID"));//:"); + + JLabel uUIDLabel = new JLabel(localization.getString("Device.UUID"));// :"); GridBagConstraints gbc_uUIDLabel = new GridBagConstraints(); gbc_uUIDLabel.anchor = GridBagConstraints.EAST; gbc_uUIDLabel.insets = new Insets(5, 5, 5, 5); gbc_uUIDLabel.gridx = 0; gbc_uUIDLabel.gridy = 2; - panel_1.add(uUIDLabel, gbc_uUIDLabel); - + informationPanel.add(uUIDLabel, gbc_uUIDLabel); + uUIDTextBox = new JTextField(); uUIDTextBox.setEditable(false); GridBagConstraints gbc_uUIDTextBox = new GridBagConstraints(); gbc_uUIDTextBox.weightx = 1.0; gbc_uUIDTextBox.gridwidth = 3; - gbc_uUIDTextBox.insets = new Insets(5, 0, 5, 5); + gbc_uUIDTextBox.insets = new Insets(5, 0, 5, 0); gbc_uUIDTextBox.fill = GridBagConstraints.HORIZONTAL; gbc_uUIDTextBox.gridx = 1; gbc_uUIDTextBox.gridy = 2; - panel_1.add(uUIDTextBox, gbc_uUIDTextBox); + informationPanel.add(uUIDTextBox, gbc_uUIDTextBox); uUIDTextBox.setColumns(10); - - JLabel FirmwareLabel = new JLabel(localization.getString("Device.firmware"));//"Firmware :"); + + JLabel FirmwareLabel = new JLabel(localization.getString("Device.firmware"));// "Firmware :"); GridBagConstraints gbc_FirmwareLabel = new GridBagConstraints(); gbc_FirmwareLabel.anchor = GridBagConstraints.EAST; gbc_FirmwareLabel.insets = new Insets(5, 0, 5, 5); gbc_FirmwareLabel.gridx = 0; gbc_FirmwareLabel.gridy = 3; - panel_1.add(FirmwareLabel, gbc_FirmwareLabel); - + informationPanel.add(FirmwareLabel, gbc_FirmwareLabel); + firmwareTextBox = new JTextField(); firmwareTextBox.setEditable(false); GridBagConstraints gbc_firmwareTextBox = new GridBagConstraints(); gbc_firmwareTextBox.weightx = 1.0; gbc_firmwareTextBox.gridwidth = 3; - gbc_firmwareTextBox.insets = new Insets(5, 0, 5, 5); + gbc_firmwareTextBox.insets = new Insets(5, 0, 5, 0); gbc_firmwareTextBox.fill = GridBagConstraints.HORIZONTAL; gbc_firmwareTextBox.gridx = 1; gbc_firmwareTextBox.gridy = 3; - panel_1.add(firmwareTextBox, gbc_firmwareTextBox); + informationPanel.add(firmwareTextBox, gbc_firmwareTextBox); firmwareTextBox.setColumns(10); - + JLabel sizeLabel = new JLabel(localization.getString("Device.size")); GridBagConstraints gbc_sizeLabel = new GridBagConstraints(); gbc_sizeLabel.anchor = GridBagConstraints.EAST; gbc_sizeLabel.insets = new Insets(5, 5, 5, 5); gbc_sizeLabel.gridx = 0; gbc_sizeLabel.gridy = 4; - panel_1.add(sizeLabel, gbc_sizeLabel); - + informationPanel.add(sizeLabel, gbc_sizeLabel); + totalSizeTextBox = new JTextField(); totalSizeTextBox.setEditable(false); GridBagConstraints gbc_totalSizeTextBox = new GridBagConstraints(); @@ -452,748 +449,865 @@ private void initialize() { gbc_totalSizeTextBox.fill = GridBagConstraints.HORIZONTAL; gbc_totalSizeTextBox.gridx = 1; gbc_totalSizeTextBox.gridy = 4; - panel_1.add(totalSizeTextBox, gbc_totalSizeTextBox); + informationPanel.add(totalSizeTextBox, gbc_totalSizeTextBox); totalSizeTextBox.setColumns(10); - + JLabel sizeUsedLabel = new JLabel(localization.getString("Device.used")); GridBagConstraints gbc_sizeUsedLabel = new GridBagConstraints(); gbc_sizeUsedLabel.insets = new Insets(5, 5, 5, 5); gbc_sizeUsedLabel.anchor = GridBagConstraints.EAST; gbc_sizeUsedLabel.gridx = 2; gbc_sizeUsedLabel.gridy = 4; - panel_1.add(sizeUsedLabel, gbc_sizeUsedLabel); - + informationPanel.add(sizeUsedLabel, gbc_sizeUsedLabel); + usedSizeTextBox = new JTextField(); usedSizeTextBox.setEditable(false); GridBagConstraints gbc_usedSizeTextBox = new GridBagConstraints(); gbc_usedSizeTextBox.weightx = 1.0; - gbc_usedSizeTextBox.insets = new Insets(5, 0, 5, 5); + gbc_usedSizeTextBox.insets = new Insets(5, 0, 5, 0); gbc_usedSizeTextBox.fill = GridBagConstraints.HORIZONTAL; gbc_usedSizeTextBox.gridx = 3; gbc_usedSizeTextBox.gridy = 4; - panel_1.add(usedSizeTextBox, gbc_usedSizeTextBox); + informationPanel.add(usedSizeTextBox, gbc_usedSizeTextBox); usedSizeTextBox.setColumns(10); - - statusPanel = new JPanel(); - panel.add(statusPanel, BorderLayout.SOUTH); - statusLayout = new GridBagLayout(); - statusLayout.columnWeights = new double[]{0.0, 1.0, 0.0, 1.0}; - statusPanel.setLayout(statusLayout); - - lblTransferingPack = new Label(""); - GridBagConstraints gbc_lblTransferingPack = new GridBagConstraints(); - gbc_lblTransferingPack.fill = GridBagConstraints.HORIZONTAL; - gbc_lblTransferingPack.insets = new Insets(0, 5, 0, 5); - gbc_lblTransferingPack.gridy = 0; - gbc_lblTransferingPack.gridx = 0; - statusPanel.add(lblTransferingPack, gbc_lblTransferingPack); - - installUninstallProgressBar = new JProgressBar(); - GridBagConstraints gbc_installUninstallProgressBar = new GridBagConstraints(); - gbc_installUninstallProgressBar.fill = GridBagConstraints.HORIZONTAL; - gbc_installUninstallProgressBar.insets = new Insets(0, 0, 0, 5); - gbc_installUninstallProgressBar.gridx = 1; - gbc_installUninstallProgressBar.gridy = 0; - statusPanel.add(installUninstallProgressBar, gbc_installUninstallProgressBar); - - Label lblProgress = new Label(localization.getString("Transfer.globalProgress")); - GridBagConstraints gbc_lblProgress = new GridBagConstraints(); - gbc_lblProgress.fill = GridBagConstraints.HORIZONTAL; - gbc_lblProgress.insets = new Insets(0, 0, 0, 5); - gbc_lblProgress.gridx = 2; - gbc_lblProgress.gridy = 0; - statusPanel.add(lblProgress, gbc_lblProgress); - - globalProgressBar = new JProgressBar(); - globalProgressBar.setStringPainted(false); - GridBagConstraints gbc_globalProgressBar = new GridBagConstraints(); - gbc_globalProgressBar.fill = GridBagConstraints.HORIZONTAL; - gbc_globalProgressBar.insets = new Insets(0, 0, 0, 5); - gbc_globalProgressBar.gridx = 3; - gbc_globalProgressBar.gridy = 0; - statusPanel.add(globalProgressBar, gbc_globalProgressBar); - + + libraryPathLabel = new JLabel("Library" + (library == null ? "" : library.getLibraryPath())); + libraryPathLabel.setFont(new Font("Lucida Grande", Font.ITALIC, 10)); + GridBagConstraints gbc_libraryPathLabel = new GridBagConstraints(); + gbc_libraryPathLabel.gridwidth = 4; + gbc_libraryPathLabel.anchor = GridBagConstraints.EAST; + gbc_libraryPathLabel.gridx = 0; + gbc_libraryPathLabel.gridy = 5; + gbc_libraryPathLabel.insets = new Insets(5, 5, 5, 5); + informationPanel.add(libraryPathLabel, gbc_libraryPathLabel); + devicePacksModel = new DefaultListModel(); - DragSource ds = new DragSource(); DragGestureListener dgl = new DragGestureListener() { @Override public void dragGestureRecognized(DragGestureEvent dge) { String source = dge.getComponent().getName(); - if ( source.equals("devices") || source.equals("library") ) { - String selectedIndices = ((JList)dge.getComponent()).getSelectedValuesList().stream().map( JsonPack::getUuid ).collect(Collectors.joining(",")); - StringSelection transferable = new StringSelection(source + ": " + selectedIndices); - ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, null); - } - }}; - + if (source.equals("devices") || source.equals("library")) { + String selectedIndices = ((JList) dge.getComponent()).getSelectedValuesList().stream() + .map(JsonPack::getUuid).collect(Collectors.joining(",")); + StringSelection transferable = new StringSelection(source + ": " + selectedIndices); + ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, null); + } + } + }; + libraryPacksModel = new DefaultListModel(); devicePacksModel.addListDataListener(new ListDataListener() { @Override public void intervalAdded(ListDataEvent e) { - devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); - + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + + devicePacksList.getModel().getSize()); + } @Override public void intervalRemoved(ListDataEvent e) { - devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); - + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + + devicePacksList.getModel().getSize()); + } @Override public void contentsChanged(ListDataEvent e) { - devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); - + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + + devicePacksList.getModel().getSize()); + } - + + }); + libraryPacksModel.addListDataListener(new ListDataListener() { + + @Override + public void intervalAdded(ListDataEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + + libraryPacksModel.getSize()); + + } + + @Override + public void intervalRemoved(ListDataEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + + libraryPacksModel.getSize()); + + } + + @Override + public void contentsChanged(ListDataEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + + libraryPacksModel.getSize()); + + } + }); - libraryPacksModel.addListDataListener(new ListDataListener() { - @Override - public void intervalAdded(ListDataEvent e) { - libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); - + JSplitPane splitPane = new JSplitPane(); + splitPane.setResizeWeight(0.5); + panel.add(splitPane, BorderLayout.CENTER); + // panel_7.add(splitPane, gbc_splitPane); + + JPanel deviceListPanel = new JPanel(); + splitPane.setLeftComponent(deviceListPanel); + deviceListPanel.setLayout(new BorderLayout(0, 0)); + deviceListPanel.setBorder(new TitledBorder(null, localization.getString("Device.list"), TitledBorder.LEADING, + TitledBorder.TOP, null, null)); + + deviceSearchTextField = new PlaceholderTextField(); + deviceListPanel.add(deviceSearchTextField, BorderLayout.NORTH); + deviceSearchTextField.setPlaceHolder(localization.getString("Device.search")); + deviceSearchTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + if ( e.getKeyChar() == KeyEvent.VK_ENTER ) { + String searchText = deviceSearchTextField.getText().toLowerCase(); + boolean found = false; + int i; + int startIndex = devicePacksList.getSelectedIndex() + 1; + for(i = startIndex; i < devicePacksModel.getSize() && !found; i++) { + JsonPack element = devicePacksModel.get(i); + found = element.getTitle() != null && element.getTitle().toLowerCase().contains(searchText) || element.getLocalizedInfos() != null && element.getLocalizedInfos().values().stream().anyMatch( (localizedInfos) -> (localizedInfos.getTitle() != null && localizedInfos.getTitle().toLowerCase().contains(searchText)) || (localizedInfos.getDescription() != null && localizedInfos.getDescription().toLowerCase().contains(searchText))); + } + if ( found ) { + devicePacksList.setSelectedIndex(i - 1); + devicePacksList.ensureIndexIsVisible(i - 1); + } else if ( startIndex > 0 ) { + devicePacksList.clearSelection(); + this.keyTyped((e)); } + } else if ( e.getKeyChar() == KeyEvent.VK_ESCAPE ) { + deviceSearchTextField.setText(""); + } + } + }); - @Override - public void intervalRemoved(ListDataEvent e) { - libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); - + JScrollPane devicePacksScrollPane = new JScrollPane(); + deviceListPanel.add(devicePacksScrollPane); + devicePacksList = new JList(devicePacksModel); + devicePacksList.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + + if (e.getExtendedKeyCode() == KeyEvent.VK_DELETE) { + int[] selection = devicePacksList.getSelectedIndices(); + for (int i = selection.length - 1; i >= 0; i--) { + devicePacksModel.remove(selection[i]); } + } else if (e.getExtendedKeyCode() == KeyEvent.VK_ESCAPE) { + devicePacksList.getSelectionModel().clearSelection(); + } + } + }); + devicePacksList.setCellRenderer(new JsonPackCell()); + devicePacksList.setName("devices"); + devicePacksScrollPane.setViewportView(devicePacksList); + devicePacksList.setDragEnabled(true); + devicePacksList.setDropMode(DropMode.INSERT); + devicePacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + + devicePacksList.getModel().getSize()); + + } + + }); + ds.createDefaultDragGestureRecognizer(devicePacksList, DnDConstants.ACTION_MOVE, dgl); + devicePacksList.setTransferHandler(new TransferHandler() { + + private static final long serialVersionUID = -6050701764610620507L; + + public boolean canImport(TransferHandler.TransferSupport support) { + if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { + return false; + } + if (!support.getComponent().getName().equals("devices")) { + return false; + } + + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + return dl.getIndex() != -1; + } + + public boolean importData(TransferHandler.TransferSupport support) { + if (!canImport(support)) { + return false; + } + + Transferable transferable = support.getTransferable(); + String transferMe; + try { + transferMe = (String) transferable.getTransferData(DataFlavor.stringFlavor); + } catch (UnsupportedFlavorException | IOException e) { + e.printStackTrace(); + return false; + } + + String source = transferMe.substring(0, transferMe.indexOf(": ")); + List uuids = List.of(transferMe.substring(transferMe.indexOf(": ") + 2).split(",")); + + JList list = source.equals("library") ? libraryPacksList + : source.equals("devices") ? devicePacksList : null; + if (list == null) + return false; + + final DefaultListModel model = ((DefaultListModel) list.getModel()); - @Override - public void contentsChanged(ListDataEvent e) { - libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); - + List indices = new ArrayList(); + for (String uuid : uuids) { + indices.add(IntStream.range(0, model.getSize()).filter(i -> uuid.equals(model.get(i).getUuid())) + .findFirst().getAsInt()); + } + + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + final Integer dropTargetIndex = dl.getIndex(); + + if (source.equals("devices")) { + int nbBeforeDropIndex = (int) indices.stream().filter((v) -> v < dropTargetIndex.intValue()) + .count(); + List objects = new ArrayList(); + for (int index = indices.size() - 1; index >= 0; index--) { + objects.add(model.remove(indices.get(index))); } - - }); - - JPanel panel_7 = new JPanel(); - panel_7.setBorder(null); - panel.add(panel_7, BorderLayout.CENTER); - GridBagLayout gbl_panel_7 = new GridBagLayout(); - gbl_panel_7.columnWidths = new int[]{0, 0}; - gbl_panel_7.rowHeights = new int[]{0, 0}; - gbl_panel_7.columnWeights = new double[]{1.0, Double.MIN_VALUE}; - gbl_panel_7.rowWeights = new double[]{1.0, Double.MIN_VALUE}; - panel_7.setLayout(gbl_panel_7); - - JSplitPane splitPane = new JSplitPane(); - splitPane.setResizeWeight(0.5); - GridBagConstraints gbc_splitPane = new GridBagConstraints(); - gbc_splitPane.fill = GridBagConstraints.BOTH; - gbc_splitPane.gridx = 0; - gbc_splitPane.gridy = 0; - gbc_splitPane.insets = new Insets(0, 5, 0, 5); - panel_7.add(splitPane, gbc_splitPane); - - JPanel panel_2 = new JPanel(); - splitPane.setLeftComponent(panel_2); - panel_2.setLayout(new BorderLayout(0, 0)); - - JScrollPane devicePacksScrollPane = new JScrollPane(); - panel_2.add(devicePacksScrollPane); - devicePacksList = new JList(devicePacksModel); - devicePacksList.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - - if ( e.getExtendedKeyCode() == KeyEvent.VK_DELETE ) { - int[] selection = devicePacksList.getSelectedIndices(); - for(int i = selection.length - 1; i >= 0; i--) { - devicePacksModel.remove(selection[i]); - } - } else if ( e.getExtendedKeyCode() == KeyEvent.VK_ESCAPE ) { - devicePacksList.getSelectionModel().clearSelection(); - } + + int insertIndex = dropTargetIndex - nbBeforeDropIndex; + + for (int i = objects.size() - 1; i >= 0; i--) { + model.add(insertIndex++, objects.get(i)); + } - }); - devicePacksList.setBorder(new TitledBorder(null, localization.getString("Device.list"), TitledBorder.LEADING, TitledBorder.TOP, null, null)); - devicePacksList.setCellRenderer( new JsonPackCell()); - devicePacksList.setName("devices"); - devicePacksScrollPane.setViewportView(devicePacksList); - devicePacksList.setDragEnabled(true); - devicePacksList.setDropMode(DropMode.INSERT); - devicePacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - - @Override - public void valueChanged(ListSelectionEvent e) { - devicePacksSummaryLabel.setText(devicePacksList.getSelectionModel().getSelectedItemsCount() + "/" + devicePacksList.getModel().getSize()); - + } else { + List existingPacks = List + .of(((DefaultListModel) ((JList) support.getComponent()).getModel()) + .toArray()); + List existingUUIDs = existingPacks.stream().map(p -> ((JsonPack) p).getUuid()).toList(); + + List toAdd = indices.stream().map(i -> model.get(i)) + .filter(pack -> existingUUIDs.stream().allMatch(s -> !s.equalsIgnoreCase(pack.getUuid()))) + .toList(); + devicePacksModel.addAll(dropTargetIndex, toAdd); + } + + return true; + } + + }); + + JPanel panel_4 = new JPanel(); + deviceListPanel.add(panel_4, BorderLayout.SOUTH); + GridBagLayout gbl_panel_4 = new GridBagLayout(); + gbl_panel_4.columnWeights = new double[] { 0.0, 0.0, 0.0, 0.0, 1.0 }; + gbl_panel_4.rowWeights = new double[] { 0.0 }; + panel_4.setLayout(gbl_panel_4); + + btnDownloadPackages = new JButton(localization.getString("Device.download"));// "Download"); + btnDownloadPackages.setEnabled(false); + GridBagConstraints gbc_btnDownloadPackages = new GridBagConstraints(); + gbc_btnDownloadPackages.anchor = GridBagConstraints.NORTHWEST; + gbc_btnDownloadPackages.insets = new Insets(0, 0, 5, 5); + gbc_btnDownloadPackages.gridx = 0; + gbc_btnDownloadPackages.gridy = 0; + panel_4.add(btnDownloadPackages, gbc_btnDownloadPackages); + btnDownloadPackages.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + + btnRefresh.setEnabled(false); + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); + btnCancel.setEnabled(true); + + CompletableFuture.runAsync(() -> { + int[] selected = devicePacksList.getSelectedIndices(); + if (selected.length == 0) { + selected = IntStream.range(0, devicePacksModel.getSize()).toArray(); } - - }); - ds.createDefaultDragGestureRecognizer(devicePacksList, DnDConstants.ACTION_MOVE, dgl); - devicePacksList.setTransferHandler(new TransferHandler() { - - private static final long serialVersionUID = -6050701764610620507L; - - public boolean canImport(TransferHandler.TransferSupport support) { - if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { - return false; - } - if ( !support.getComponent().getName().equals("devices")) { - return false; - } - - JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); - return dl.getIndex() != -1; - } - - public boolean importData(TransferHandler.TransferSupport support) { - if (!canImport(support)) { - return false; - } - - Transferable transferable = support.getTransferable(); - String transferMe; - try { - transferMe = (String)transferable.getTransferData(DataFlavor.stringFlavor); - } catch (UnsupportedFlavorException | IOException e) { - e.printStackTrace(); - return false; + globalProgressBar.setString("0/" + selected.length); + globalProgressBar.setStringPainted(true); + globalProgressBar.setMaximum(selected.length); + + Arrays.stream(selected).boxed().map((i) -> devicePacksModel.get(i)).forEach((pack) -> { + boolean mustCancelLocal = false; + synchronized (this) { + mustCancelLocal = mustCancel; } - - String source = transferMe.substring(0, transferMe.indexOf(": ")); - List uuids = List.of(transferMe.substring(transferMe.indexOf(": ") + 2).split(",")); - - JList list = source.equals("library") ? libraryPacksList : source.equals("devices") ? devicePacksList : null; - if ( list == null ) return false; - - final DefaultListModel model = ((DefaultListModel)list.getModel()); - - List indices = new ArrayList(); - for(String uuid :uuids ) { - indices.add(IntStream.range(0, model.getSize()) - .filter( i -> uuid.equals(model.get(i).getUuid())) - .findFirst() - .getAsInt()); - } - - JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); - final Integer dropTargetIndex = dl.getIndex(); - - if ( source.equals("devices") ) { - int nbBeforeDropIndex = (int)indices.stream().filter( (v) -> v < dropTargetIndex.intValue() ).count(); - List objects = new ArrayList(); - for(int index = indices.size() - 1; index >= 0; index-- ) { - objects.add(model.remove(indices.get(index))); - } - - int insertIndex = dropTargetIndex - nbBeforeDropIndex; - - for(int i = objects.size() - 1; i >= 0; i-- ) { - model.add(insertIndex++, objects.get(i)); - - } - } else { - List existingPacks = List.of( ((DefaultListModel)((JList)support.getComponent()).getModel()).toArray()); - List existingUUIDs = existingPacks.stream() - .map( p -> ((JsonPack)p).getUuid() ) - .toList(); - - List toAdd = indices.stream() - .map( i -> model.get(i)) - .filter( pack -> existingUUIDs.stream().allMatch(s -> !s.equalsIgnoreCase(pack.getUuid())) ) - .toList(); - devicePacksModel.addAll(dropTargetIndex, toAdd); - } - - - return true; - } - - }); - - JPanel panel_4 = new JPanel(); - panel_2.add(panel_4, BorderLayout.SOUTH); - GridBagLayout gbl_panel_4 = new GridBagLayout(); - gbl_panel_4.columnWeights = new double[]{0.0, 0.0, 0.0, 0.0, 1.0}; - gbl_panel_4.rowWeights = new double[]{0.0}; - panel_4.setLayout(gbl_panel_4); - - btnDownloadPackages = new JButton(localization.getString("Device.download"));//"Download"); - btnDownloadPackages.setEnabled(false); - GridBagConstraints gbc_btnDownloadPackages = new GridBagConstraints(); - gbc_btnDownloadPackages.anchor = GridBagConstraints.NORTHWEST; - gbc_btnDownloadPackages.insets = new Insets(0, 0, 5, 5); - gbc_btnDownloadPackages.gridx = 0; - gbc_btnDownloadPackages.gridy = 0; - panel_4.add(btnDownloadPackages, gbc_btnDownloadPackages); - btnDownloadPackages.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - - btnRefresh.setEnabled(false); - btnDownloadPackages.setEnabled(false); - btnValidate.setEnabled(false); - btnCancel.setEnabled(true); - - - CompletableFuture.runAsync( () -> { - int[] selected = devicePacksList.getSelectedIndices(); - if ( selected.length == 0 ) { - selected = IntStream.range(0, devicePacksModel.getSize()).toArray(); - } - globalProgressBar.setString("0/" + selected.length); - globalProgressBar.setStringPainted(true); - globalProgressBar.setMaximum(selected.length); - - Arrays.stream(selected).boxed().map( (i) -> devicePacksModel.get(i)).forEach( (pack) -> { - boolean mustCancelLocal = false; - synchronized(this) { - mustCancelLocal = mustCancel; - } - if ( fsDriverUsed && !mustCancelLocal) { - try { - - JsonPack jsonPack = library.getPackForUUID(pack.getUuid()).get(); - String packTitle = jsonPack.getTitle(); - if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); - lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); - fsDriver.downloadPack(pack.getUuid(), library.getLibraryPath(), new TransferProgressListener() { - + if (fsDriverUsed && !mustCancelLocal) { + try { + + JsonPack jsonPack = library.getPackForUUID(pack.getUuid()).get(); + String packTitle = jsonPack.getTitle(); + if (packTitle == null) + packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack") + .replace("{}", packTitle)); + fsDriver.downloadPack(pack.getUuid(), library.getLibraryPath(), + new TransferProgressListener() { + @Override public void onProgress(TransferStatus status) { installUninstallProgressBar.setMinimum(0); installUninstallProgressBar.setMaximum(status.getTotal()); installUninstallProgressBar.setValue(status.getTransferred()); - + } - + @Override public void onComplete(TransferStatus status) { } }).get(); - - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } finally { - installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); - } - } else if ( rawDriverUsed && !mustCancelLocal) { - try { - JsonPack jsonPack = library.getPackForUUID(pack.getUuid()).get(); - String packTitle = jsonPack.getTitle(); - if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); - lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); - - rawDriver.downloadPack(pack.getUuid(), Files.newOutputStream(Paths.get(library.getLibraryPath(), pack.getUuid() + ".pack")), new TransferProgressListener() { - + + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar + .setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + } + } else if (rawDriverUsed && !mustCancelLocal) { + try { + JsonPack jsonPack = library.getPackForUUID(pack.getUuid()).get(); + String packTitle = jsonPack.getTitle(); + if (packTitle == null) + packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack") + .replace("{}", packTitle)); + + rawDriver.downloadPack(pack.getUuid(), + Files.newOutputStream( + Paths.get(library.getLibraryPath(), pack.getUuid() + ".pack")), + new TransferProgressListener() { + @Override public void onProgress(TransferStatus status) { installUninstallProgressBar.setMinimum(0); installUninstallProgressBar.setMaximum(status.getTotal()); installUninstallProgressBar.setValue(status.getTransferred()); } - + @Override public void onComplete(TransferStatus status) { } }).get(); - } catch (IOException | InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } finally { - installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); - } - } - }); - - synchronized (this) { - mustCancel = false; + } catch (IOException | InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar + .setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } - - lblTransferingPack.setText(""); - installUninstallProgressBar.setValue(0); - globalProgressBar.setValue(0); - globalProgressBar.setStringPainted(false); - btnRefresh.setEnabled(true); - btnDownloadPackages.setEnabled(true); - btnValidate.setEnabled(true); - btnCancel.setEnabled(false); - }); - + } + }); + + synchronized (this) { + mustCancel = false; } + + lblTransferingPack.setText(""); + installUninstallProgressBar.setValue(0); + globalProgressBar.setValue(0); + globalProgressBar.setStringPainted(false); + btnRefresh.setEnabled(true); + btnDownloadPackages.setEnabled(true); + btnValidate.setEnabled(true); + btnCancel.setEnabled(false); }); - - btnValidate = new JButton(localization.getString("Device.validate"));//"Validate"); + + } + }); + + btnValidate = new JButton(localization.getString("Device.validate"));// "Validate"); + btnValidate.setEnabled(false); + GridBagConstraints gbc_btnValidate = new GridBagConstraints(); + gbc_btnValidate.anchor = GridBagConstraints.NORTHWEST; + gbc_btnValidate.insets = new Insets(0, 0, 5, 5); + gbc_btnValidate.gridx = 1; + gbc_btnValidate.gridy = 0; + panel_4.add(btnValidate, gbc_btnValidate); + btnValidate.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + btnRefresh.setEnabled(false); btnValidate.setEnabled(false); - GridBagConstraints gbc_btnValidate = new GridBagConstraints(); - gbc_btnValidate.anchor = GridBagConstraints.NORTHWEST; - gbc_btnValidate.insets = new Insets(0, 0, 5, 5); - gbc_btnValidate.gridx = 1; - gbc_btnValidate.gridy = 0; - panel_4.add(btnValidate, gbc_btnValidate); - btnValidate.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - btnRefresh.setEnabled(false); - btnValidate.setEnabled(false); - btnDownloadPackages.setEnabled(false); - btnCancel.setEnabled(true); - - loadPacksFromDevice().thenAcceptAsync( (packs) -> { - try { - - List uuids = packs.stream().map( pack -> pack.getUuid()).toList(); - List uuidsInList = Arrays.asList(devicePacksModel.toArray()).stream().map( pack -> ((JsonPack) pack).getUuid()).toList(); - - // Packs to uninstall - List toUninstall = new ArrayList(uuids); - toUninstall.removeAll(uuidsInList); - - // Packs to add - List toInstall = new ArrayList(uuidsInList); - toInstall.removeAll(uuids); - - int nbSteps = toUninstall.size() + toInstall.size() + 1; - boolean mustCancelLocal = false; - - globalProgressBar.setMinimum(0); - globalProgressBar.setMaximum(nbSteps); - globalProgressBar.setValue(0); - globalProgressBar.setString("0/" + nbSteps); - globalProgressBar.setStringPainted(true); - - synchronized(this) { - mustCancelLocal = mustCancel; - } - if ( fsDriverUsed && !mustCancelLocal ) { - toUninstall.forEach( (pack) -> { - try { - synchronized(this) { - if ( mustCancel ) return; - } - JsonPack jsonPack = library.getPackForUUID(pack).get(); - String packTitle = jsonPack.getTitle(); - if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); - lblTransferingPack.setText(localization.getString("Transfering.deletingpack").replace("{}", packTitle)); - statusPanel.updateUI(); - fsDriver.deletePack(pack).get(); - - refreshFreeSpaceOnDevice(); - } catch (InterruptedException | ExecutionException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); - } - }); - } else if ( rawDriverUsed && !mustCancelLocal ) { - toUninstall.forEach( (pack) -> { - try { - synchronized(this) { - if ( mustCancel ) return; - } - JsonPack jsonPack = library.getPackForUUID(pack).get(); - String packTitle = jsonPack.getTitle(); - if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); - lblTransferingPack.setText(localization.getString("Transfering.deletingpack").replace("{}", packTitle)); - statusPanel.updateUI(); - rawDriver.deletePack(pack).get(); - - refreshFreeSpaceOnDevice(); - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + btnDownloadPackages.setEnabled(false); + btnCancel.setEnabled(true); + + loadPacksFromDevice().thenAcceptAsync((packs) -> { + try { + + List uuids = packs.stream().map(pack -> pack.getUuid()).toList(); + List uuidsInList = Arrays.asList(devicePacksModel.toArray()).stream() + .map(pack -> ((JsonPack) pack).getUuid()).toList(); + + // Packs to uninstall + List toUninstall = new ArrayList(uuids); + toUninstall.removeAll(uuidsInList); + + // Packs to add + List toInstall = new ArrayList(uuidsInList); + toInstall.removeAll(uuids); + + int nbSteps = toUninstall.size() + toInstall.size() + 1; + boolean mustCancelLocal = false; + + globalProgressBar.setMinimum(0); + globalProgressBar.setMaximum(nbSteps); + globalProgressBar.setValue(0); + globalProgressBar.setString("0/" + nbSteps); + globalProgressBar.setStringPainted(true); + + synchronized (this) { + mustCancelLocal = mustCancel; + } + if (fsDriverUsed && !mustCancelLocal) { + toUninstall.forEach((pack) -> { + try { + synchronized (this) { + if (mustCancel) + return; } - }); - } - - - TransferProgressListener progressListener = new TransferProgressListener() { - - @Override - public void onProgress(TransferStatus status) { - installUninstallProgressBar.setMinimum(0); - installUninstallProgressBar.setMaximum(status.getTotal()); - installUninstallProgressBar.setValue(status.getTransferred()); - - } - - @Override - public void onComplete(TransferStatus status) { - installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if (packTitle == null) + packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.deletingpack") + .replace("{}", packTitle)); + statusPanel.updateUI(); + fsDriver.deletePack(pack).get(); + + refreshFreeSpaceOnDevice(); + } catch (InterruptedException | ExecutionException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString( + globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } - }; - - synchronized(this) { - mustCancelLocal = mustCancel; - } - if ( fsDriverUsed && !mustCancelLocal ) { - toInstall.forEach( (pack) -> { - try { - synchronized(this) { - if ( mustCancel ) return; - } - JsonPack jsonPack = library.getPackForUUID(pack).get(); - String packTitle = jsonPack.getTitle(); - if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); - lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); - statusPanel.updateUI(); - fsDriver.uploadPack(pack, library.getFolderForUUID(pack), progressListener).get(); - - refreshFreeSpaceOnDevice(); - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); - } - }); - } else if ( rawDriverUsed && !mustCancelLocal) { - toInstall.forEach( (pack) -> { - try { - synchronized(this) { - if ( mustCancel ) return; - } - JsonPack jsonPack = library.getPackForUUID(pack).get(); - String packTitle = jsonPack.getTitle(); - if ( packTitle == null ) packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); - lblTransferingPack.setText(localization.getString("Transfering.transferringpack").replace("{}", packTitle)); - statusPanel.updateUI(); - rawDriver.uploadPack(null, 0, progressListener).get(); - - refreshFreeSpaceOnDevice(); - } catch (InterruptedException | ExecutionException e1) { - e1.printStackTrace(); - } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + }); + } else if (rawDriverUsed && !mustCancelLocal) { + toUninstall.forEach((pack) -> { + try { + synchronized (this) { + if (mustCancel) + return; } - }); + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if (packTitle == null) + packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.deletingpack") + .replace("{}", packTitle)); + statusPanel.updateUI(); + rawDriver.deletePack(pack).get(); + + refreshFreeSpaceOnDevice(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString( + globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + } + }); + } + + TransferProgressListener progressListener = new TransferProgressListener() { + + @Override + public void onProgress(TransferStatus status) { + installUninstallProgressBar.setMinimum(0); + installUninstallProgressBar.setMaximum(status.getTotal()); + installUninstallProgressBar.setValue(status.getTransferred()); + } - - // Reorder packs - synchronized(this) { - mustCancelLocal = mustCancel; + + @Override + public void onComplete(TransferStatus status) { + installUninstallProgressBar.setValue(installUninstallProgressBar.getMaximum()); } - if ( fsDriverUsed && !mustCancelLocal) { + }; + + synchronized (this) { + mustCancelLocal = mustCancel; + } + if (fsDriverUsed && !mustCancelLocal) { + toInstall.forEach((pack) -> { try { - lblTransferingPack.setText(localization.getString("Transfering.reordering")); + synchronized (this) { + if (mustCancel) + return; + } + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if (packTitle == null) + packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack") + .replace("{}", packTitle)); statusPanel.updateUI(); - - fsDriver.reorderPacks(uuidsInList).get(); + fsDriver.uploadPack(pack, library.getFolderForUUID(pack), progressListener).get(); + + refreshFreeSpaceOnDevice(); } catch (InterruptedException | ExecutionException e1) { e1.printStackTrace(); } finally { - globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar.setString( + globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } - } else { + }); + } else if (rawDriverUsed && !mustCancelLocal) { + toInstall.forEach((pack) -> { try { - rawDriver.reorderPacks(uuidsInList).get(); + synchronized (this) { + if (mustCancel) + return; + } + JsonPack jsonPack = library.getPackForUUID(pack).get(); + String packTitle = jsonPack.getTitle(); + if (packTitle == null) + packTitle = jsonPack.getLocalizedInfos().values().iterator().next().getTitle(); + lblTransferingPack.setText(localization.getString("Transfering.transferringpack") + .replace("{}", packTitle)); + statusPanel.updateUI(); + rawDriver.uploadPack(null, 0, progressListener).get(); + + refreshFreeSpaceOnDevice(); } catch (InterruptedException | ExecutionException e1) { e1.printStackTrace(); } finally { globalProgressBar.setValue(globalProgressBar.getValue() + 1); - globalProgressBar.setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); - + globalProgressBar.setString( + globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } + }); + } + + // Reorder packs + synchronized (this) { + mustCancelLocal = mustCancel; + } + if (fsDriverUsed && !mustCancelLocal) { + try { + lblTransferingPack.setText(localization.getString("Transfering.reordering")); + statusPanel.updateUI(); + + fsDriver.reorderPacks(uuidsInList).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar + .setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); } - - } catch(Exception e2) { - e2.printStackTrace(); - } - - synchronized(this) { - mustCancel = false; + } else { + try { + rawDriver.reorderPacks(uuidsInList).get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + } finally { + globalProgressBar.setValue(globalProgressBar.getValue() + 1); + globalProgressBar + .setString(globalProgressBar.getValue() + "/" + globalProgressBar.getMaximum()); + } - btnRefresh.setEnabled(true); - btnValidate.setEnabled(true); - btnCancel.setEnabled(false); - btnDownloadPackages.setEnabled(true); - lblTransferingPack.setText(localization.getString("Transfering.done")); - - installUninstallProgressBar.setValue(0); - globalProgressBar.setValue(0); - globalProgressBar.setString(null); - statusPanel.updateUI(); - }); + } + + } catch (Exception e2) { + e2.printStackTrace(); } + + synchronized (this) { + mustCancel = false; + } + btnRefresh.setEnabled(true); + btnValidate.setEnabled(true); + btnCancel.setEnabled(false); + btnDownloadPackages.setEnabled(true); + lblTransferingPack.setText(localization.getString("Transfering.done")); + + installUninstallProgressBar.setValue(0); + globalProgressBar.setValue(0); + globalProgressBar.setString(null); + statusPanel.updateUI(); }); - - btnRefresh = new JButton(localization.getString("Device.refresh"));//"Refresh from device"); + } + }); + + btnRefresh = new JButton(localization.getString("Device.refresh"));// "Refresh from device"); + btnRefresh.setEnabled(false); + GridBagConstraints gbc_btnRefersh = new GridBagConstraints(); + gbc_btnRefersh.anchor = GridBagConstraints.NORTHWEST; + gbc_btnRefersh.insets = new Insets(0, 0, 5, 5); + gbc_btnRefersh.gridx = 2; + gbc_btnRefersh.gridy = 0; + panel_4.add(btnRefresh, gbc_btnRefersh); + btnRefresh.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + btnDownloadPackages.setEnabled(false); + btnValidate.setEnabled(false); btnRefresh.setEnabled(false); - GridBagConstraints gbc_btnRefersh = new GridBagConstraints(); - gbc_btnRefersh.anchor = GridBagConstraints.NORTHWEST; - gbc_btnRefersh.insets = new Insets(0, 0, 5, 5); - gbc_btnRefersh.gridx = 2; - gbc_btnRefersh.gridy = 0; - panel_4.add(btnRefresh, gbc_btnRefersh); - btnRefresh.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - btnDownloadPackages.setEnabled(false); - btnValidate.setEnabled(false); - btnRefresh.setEnabled(false); - - devicePacksModel.clear(); - loadPacksFromDevice().thenAcceptAsync( (packs) -> { - devicePacksModel.clear(); - devicePacksModel.addAll(packs); - - btnDownloadPackages.setEnabled(true); - btnValidate.setEnabled(true); - btnRefresh.setEnabled(true); - }); - - } + + devicePacksModel.clear(); + loadPacksFromDevice().thenAcceptAsync((packs) -> { + devicePacksModel.clear(); + devicePacksModel.addAll(packs); + + btnDownloadPackages.setEnabled(true); + btnValidate.setEnabled(true); + btnRefresh.setEnabled(true); }); - - btnCancel = new JButton(localization.getString("Device.cancel")); - - btnCancel.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - synchronized(this) { - mustCancel = true; + + } + }); + + btnCancel = new JButton(localization.getString("Device.cancel")); + + btnCancel.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + synchronized (this) { + mustCancel = true; + } + btnCancel.setEnabled(false); + } + }); + btnCancel.setEnabled(false); + GridBagConstraints gbc_btnCancel = new GridBagConstraints(); + gbc_btnCancel.anchor = GridBagConstraints.NORTHWEST; + gbc_btnCancel.insets = new Insets(0, 0, 5, 5); + gbc_btnCancel.gridx = 3; + gbc_btnCancel.gridy = 0; + panel_4.add(btnCancel, gbc_btnCancel); + + devicePacksSummaryLabel = new JLabel("-/-"); + GridBagConstraints gbc_devicePacksSummaryLabel = new GridBagConstraints(); + gbc_devicePacksSummaryLabel.insets = new Insets(0, 0, 5, 5); + gbc_devicePacksSummaryLabel.anchor = GridBagConstraints.EAST; + gbc_devicePacksSummaryLabel.gridx = 4; + gbc_devicePacksSummaryLabel.gridy = 0; + panel_4.add(devicePacksSummaryLabel, gbc_devicePacksSummaryLabel); + + JPanel libraryListPanel = new JPanel(); + splitPane.setRightComponent(libraryListPanel); + libraryListPanel.setLayout(new BorderLayout(0, 0)); + libraryListPanel.setBorder(new TitledBorder(null, localization.getString("Library.list"), TitledBorder.LEADING, + TitledBorder.TOP, null, null)); + + JScrollPane libraryPacksScrollPane = new JScrollPane(); + libraryListPanel.add(libraryPacksScrollPane); + libraryPacksList = new JList(libraryPacksModel); + libraryPacksScrollPane.setViewportView(libraryPacksList); + libraryPacksList.setName("library"); + libraryPacksList.setCellRenderer(new JsonPackCell()); + libraryPacksList.setDragEnabled(true); + libraryPacksList.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent evt) { + JList list = (JList) evt.getSource(); + if (evt.getClickCount() == 2) { + int index = list.locationToIndex(evt.getPoint()); + if (index == -1) + return; + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Locale currentLocale = Locale.getDefault(); + JsonPack story = libraryPacksModel.get(index); + String slug = story.getSlug(); + + try { + String url = "https://lunii.com/" + currentLocale.getCountry().toLowerCase() + "-" + + currentLocale.getLanguage() + "/luniistore-catalogue/" + slug; + Desktop.getDesktop().browse(new URI(url)); + } catch (IOException | URISyntaxException e1) { } - btnCancel.setEnabled(false); + } - }); - btnCancel.setEnabled(false); - GridBagConstraints gbc_btnCancel = new GridBagConstraints(); - gbc_btnCancel.insets = new Insets(0, 0, 5, 5); - gbc_btnCancel.gridx = 3; - gbc_btnCancel.gridy = 0; - panel_4.add(btnCancel, gbc_btnCancel); - - devicePacksSummaryLabel = new JLabel("-/-"); - GridBagConstraints gbc_devicePacksSummaryLabel = new GridBagConstraints(); - gbc_devicePacksSummaryLabel.insets = new Insets(0, 0, 5, 0); - gbc_devicePacksSummaryLabel.anchor = GridBagConstraints.EAST; - gbc_devicePacksSummaryLabel.gridx = 4; - gbc_devicePacksSummaryLabel.gridy = 0; - panel_4.add(devicePacksSummaryLabel, gbc_devicePacksSummaryLabel); - - JPanel panel_5 = new JPanel(); - splitPane.setRightComponent(panel_5); - panel_5.setLayout(new BorderLayout(0, 0)); - - JPanel panel_6 = new JPanel(); - panel_5.add(panel_6, BorderLayout.SOUTH); - GridBagLayout gbl_panel_6 = new GridBagLayout(); - gbl_panel_6.columnWeights = new double[]{0.0, 1.0}; - gbl_panel_6.rowWeights = new double[]{0.0}; - panel_6.setLayout(gbl_panel_6); - - btnRefreshLibrary = new JButton(localization.getString("Library.refresh"));//"Refresh library"); + } + } + }); + libraryPacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + + libraryPacksModel.getSize()); + + } + + }); + libraryPacksList.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + + if (e.getExtendedKeyCode() == KeyEvent.VK_ESCAPE) { + libraryPacksList.getSelectionModel().clearSelection(); + } + } + }); + + ds.createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); + + libraryPacksList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + // TransferHandler transferHandler = libraryPacksList.getTransferHandler(); + + JPanel panel_6 = new JPanel(); + libraryListPanel.add(panel_6, BorderLayout.SOUTH); + GridBagLayout gbl_panel_6 = new GridBagLayout(); + gbl_panel_6.columnWeights = new double[] { 0.0, 0.0, 1.0 }; + panel_6.setLayout(gbl_panel_6); + panel_6.setMinimumSize(new Dimension(100, 100)); + + btnRefreshLibrary = new JButton(localization.getString("Library.refresh"));// "Refresh library"); + btnRefreshLibrary.setEnabled(false); + GridBagConstraints gbc_btnRefreshLibrary = new GridBagConstraints(); + gbc_btnRefreshLibrary.anchor = GridBagConstraints.NORTHWEST; + gbc_btnRefreshLibrary.insets = new Insets(0, 0, 0, 5); + gbc_btnRefreshLibrary.gridx = 0; + gbc_btnRefreshLibrary.gridy = 0; + panel_6.add(btnRefreshLibrary, gbc_btnRefreshLibrary); + btnRefreshLibrary.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { btnRefreshLibrary.setEnabled(false); - GridBagConstraints gbc_btnRefreshLibrary = new GridBagConstraints(); - gbc_btnRefreshLibrary.anchor = GridBagConstraints.NORTHWEST; - gbc_btnRefreshLibrary.insets = new Insets(0, 0, 0, 5); - gbc_btnRefreshLibrary.gridx = 0; - gbc_btnRefreshLibrary.gridy = 0; - panel_6.add(btnRefreshLibrary, gbc_btnRefreshLibrary); - btnRefreshLibrary.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - btnRefreshLibrary.setEnabled(false); - libraryPacksModel.clear(); - //libraryPacksList.setListData(new JsonPack[0]); - library.refreshDatabase().thenRunAsync( () -> { - library.getPacks().thenAcceptAsync( (List packs) -> { - libraryPacksModel.addAll(packs); - btnRefreshLibrary.setEnabled(true); - - }); - }); - - } + libraryPacksModel.clear(); + library.refreshDatabase().thenRunAsync(() -> { + library.getPacks().thenAcceptAsync((List packs) -> { + libraryPacksModel.addAll(packs); + btnRefreshLibrary.setEnabled(true); + + }); }); - - libraryPacksSummaryLabel = new JLabel("-/-"); - GridBagConstraints gbc_libraryPacksSummaryLabel = new GridBagConstraints(); - gbc_libraryPacksSummaryLabel.anchor = GridBagConstraints.EAST; - gbc_libraryPacksSummaryLabel.gridx = 1; - gbc_libraryPacksSummaryLabel.gridy = 0; - panel_6.add(libraryPacksSummaryLabel, gbc_libraryPacksSummaryLabel); - - - - JScrollPane libraryPacksScrollPane = new JScrollPane(); - panel_5.add(libraryPacksScrollPane); - libraryPacksScrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - libraryPacksList = new JList(libraryPacksModel); - libraryPacksList.setBorder(new TitledBorder(null, localization.getString("Library.list"), TitledBorder.LEADING, TitledBorder.TOP, null, null)); - libraryPacksScrollPane.setViewportView(libraryPacksList); - libraryPacksList.setName("library"); - libraryPacksList.setCellRenderer( new JsonPackCell()); - libraryPacksList.setDragEnabled(true); - libraryPacksList.addMouseListener( new MouseAdapter() { - public void mouseClicked(MouseEvent evt) { - JList list = (JList)evt.getSource(); - if (evt.getClickCount() == 2) { - int index = list.locationToIndex(evt.getPoint()); - if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - Locale currentLocale = Locale.getDefault(); - JsonPack story = libraryPacksModel.get(index); - String slug = story.getSlug(); -// if ( story.getPreviews() != null && story.getPreviews().size() > 0 ) { - try { -// String storyName = story.getPreviews().get(0).split("/")[3];// story.getTitle().replaceAll(" ", "-").toLowerCase(); - String url = "https://lunii.com/" + currentLocale.getCountry().toLowerCase() + "-" + currentLocale.getLanguage() + "/luniistore-catalogue/" + slug; - Desktop.getDesktop().browse(new URI(url)); - } catch (IOException | URISyntaxException e1) { - } -// } else { -// story.getLocalizedInfos().entrySet().stream().filter( (infos) -> infos.getValue().getPreviews().size() > 0).findFirst().ifPresent( ( entrySet ) -> { -// String storyName = entrySet.getValue().getPreviews().get(0).split("/")[3];// story.getTitle().replaceAll(" ", "-").toLowerCase(); -// String url = "https://lunii.com/" + currentLocale.getCountry().toLowerCase() + "-" + currentLocale.getLanguage() + "/luniistore-catalogue/" + storyName; -// try { -// Desktop.getDesktop().browse(new URI(url)); -// } catch (IOException | URISyntaxException e) { -// // TODO Auto-generated catch block -// e.printStackTrace(); -// } -// }); -// } - - } - } - } - }); - libraryPacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - libraryPacksSummaryLabel.setText(libraryPacksList.getSelectionModel().getSelectedItemsCount() + "/" + libraryPacksModel.getSize()); - - } - - }); - libraryPacksList.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - - if ( e.getExtendedKeyCode() == KeyEvent.VK_ESCAPE ) { - libraryPacksList.getSelectionModel().clearSelection(); - } - } - }); - + } + }); + + displayOnlyNotOnDeviceCheckBox = new JCheckBox(localization.getString("Library.filteronlynotpresentonbox")); + displayOnlyNotOnDeviceCheckBox.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + boolean filter = displayOnlyNotOnDeviceCheckBox.isSelected(); + if ( filter ) { + library.getPacks().thenAcceptAsync( (List list) -> { + libraryPacksModel.clear(); + List filtered = list.stream().filter( (JsonPack p) -> { + return !devicePacksModel.contains(p); + }).toList(); + libraryPacksModel.addAll(filtered); + }); + } else { + library.getPacks().thenAcceptAsync( (List list) -> { + libraryPacksModel.clear(); + libraryPacksModel.addAll(list); + }); + } + } + }); + GridBagConstraints gbc_displayOnlyNotOnDeviceCheckBox = new GridBagConstraints(); + gbc_displayOnlyNotOnDeviceCheckBox.anchor = GridBagConstraints.NORTHWEST; + gbc_displayOnlyNotOnDeviceCheckBox.insets = new Insets(0, 0, 0, 5); + gbc_displayOnlyNotOnDeviceCheckBox.gridx = 1; + gbc_displayOnlyNotOnDeviceCheckBox.gridy = 0; + panel_6.add(displayOnlyNotOnDeviceCheckBox, gbc_displayOnlyNotOnDeviceCheckBox); - ds.createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); - - libraryPacksList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - //TransferHandler transferHandler = libraryPacksList.getTransferHandler(); + libraryPacksSummaryLabel = new JLabel("-/-"); + GridBagConstraints gbc_libraryPacksSummaryLabel = new GridBagConstraints(); + gbc_libraryPacksSummaryLabel.anchor = GridBagConstraints.EAST; + gbc_libraryPacksSummaryLabel.gridx = 2; + gbc_libraryPacksSummaryLabel.gridy = 0; + panel_6.add(libraryPacksSummaryLabel, gbc_libraryPacksSummaryLabel); + librarySearchTextField = new PlaceholderTextField(); + librarySearchTextField.setPlaceHolder(localization.getString("Library.search")); + libraryListPanel.add(librarySearchTextField, BorderLayout.NORTH); + librarySearchTextField.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + if ( e.getKeyChar() == KeyEvent.VK_ENTER ) { + String searchText = librarySearchTextField.getText().toLowerCase(); + boolean found = false; + int i; + int startIndex = libraryPacksList.getSelectedIndex() + 1; + for(i = startIndex; i < libraryPacksModel.getSize() && !found; i++) { + JsonPack element = libraryPacksModel.get(i); + found = element.getTitle() != null && element.getTitle().toLowerCase().contains(searchText) || element.getLocalizedInfos() != null && element.getLocalizedInfos().values().stream().anyMatch( (localizedInfos) -> (localizedInfos.getTitle() != null && localizedInfos.getTitle().toLowerCase().contains(searchText)) || (localizedInfos.getDescription() != null && localizedInfos.getDescription().toLowerCase().contains(searchText))); + } + if ( found ) { + libraryPacksList.setSelectedIndex(i - 1); + libraryPacksList.ensureIndexIsVisible(i - 1); + } else if ( startIndex > 0 ) { + libraryPacksList.clearSelection(); + this.keyTyped((e)); + } + } else if ( e.getKeyChar() == KeyEvent.VK_ESCAPE ) { + librarySearchTextField.setText(""); + } + } + }); + +// JPanel panel_7 = new JPanel(); +// panel_7.setBorder(null); +// panel.add(panel_7, BorderLayout.CENTER); +// GridBagLayout gbl_panel_7 = new GridBagLayout(); +// gbl_panel_7.columnWidths = new int[]{0, 0}; +// gbl_panel_7.rowHeights = new int[]{0, 0}; +// gbl_panel_7.columnWeights = new double[]{1.0, Double.MIN_VALUE}; +// gbl_panel_7.rowWeights = new double[]{1.0, Double.MIN_VALUE}; +// panel_7.setLayout(gbl_panel_7); + + statusPanel = new JPanel(); + panel.add(statusPanel, BorderLayout.SOUTH); + statusLayout = new GridBagLayout(); + statusLayout.columnWeights = new double[] { 0.0, 1.0, 0.0, 1.0 }; + statusPanel.setLayout(statusLayout); + + lblTransferingPack = new Label(localization.getString("Transfer.notransfer")); + GridBagConstraints gbc_lblTransferingPack = new GridBagConstraints(); + gbc_lblTransferingPack.fill = GridBagConstraints.HORIZONTAL; + gbc_lblTransferingPack.insets = new Insets(0, 5, 0, 5); + gbc_lblTransferingPack.gridy = 0; + gbc_lblTransferingPack.gridx = 0; + statusPanel.add(lblTransferingPack, gbc_lblTransferingPack); + + installUninstallProgressBar = new JProgressBar(); + GridBagConstraints gbc_installUninstallProgressBar = new GridBagConstraints(); + gbc_installUninstallProgressBar.fill = GridBagConstraints.HORIZONTAL; + gbc_installUninstallProgressBar.insets = new Insets(0, 0, 0, 5); + gbc_installUninstallProgressBar.gridx = 1; + gbc_installUninstallProgressBar.gridy = 0; + statusPanel.add(installUninstallProgressBar, gbc_installUninstallProgressBar); + + Label lblProgress = new Label(localization.getString("Transfer.globalProgress")); + GridBagConstraints gbc_lblProgress = new GridBagConstraints(); + gbc_lblProgress.fill = GridBagConstraints.HORIZONTAL; + gbc_lblProgress.insets = new Insets(0, 0, 0, 5); + gbc_lblProgress.gridx = 2; + gbc_lblProgress.gridy = 0; + statusPanel.add(lblProgress, gbc_lblProgress); + + globalProgressBar = new JProgressBar(); + globalProgressBar.setStringPainted(false); + GridBagConstraints gbc_globalProgressBar = new GridBagConstraints(); + gbc_globalProgressBar.fill = GridBagConstraints.HORIZONTAL; + gbc_globalProgressBar.insets = new Insets(0, 0, 0, 5); + gbc_globalProgressBar.gridx = 3; + gbc_globalProgressBar.gridy = 0; + statusPanel.add(globalProgressBar, gbc_globalProgressBar); + GridBagConstraints gbc_splitPane = new GridBagConstraints(); + gbc_splitPane.fill = GridBagConstraints.BOTH; + gbc_splitPane.gridx = 0; + gbc_splitPane.gridy = 0; + gbc_splitPane.insets = new Insets(0, 5, 0, 5); + JMenuBar menuBar = new JMenuBar(); frmLuniiTransfer.setJMenuBar(menuBar); - - JMenu mnNewMenu = new JMenu(localization.getString("File.title"));//"File"); + + JMenu mnNewMenu = new JMenu(localization.getString("File.title"));// "File"); mnNewMenu.setMnemonic('F'); menuBar.add(mnNewMenu); - - JMenuItem mntmNewMenuItem = new JMenuItem(localization.getString("File.quit"));//"Quit"); + + JMenuItem mntmNewMenuItem = new JMenuItem(localization.getString("File.quit"));// "Quit"); mntmNewMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { frmLuniiTransfer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); @@ -1201,81 +1315,105 @@ public void actionPerformed(ActionEvent e) { } }); - - JMenuItem changeLibraryPathMenuItem = new JMenuItem(localization.getString("Library.changePath"));//"Change library path..."); + + JMenuItem changeLibraryPathMenuItem = new JMenuItem(localization.getString("Library.changePath"));// "Change + // library + // path..."); changeLibraryPathMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new java.io.File(library.getLibraryPath())); - chooser.setDialogTitle(localization.getString("Library.ChooseLibraryFolder"));//"Choose library folder"); - chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - chooser.setAcceptAllFileFilterUsed(false); - if ( chooser.showOpenDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION ) { - library = Library.getInstance(chooser.getSelectedFile().getAbsolutePath()); - btnRefreshLibrary.doClick(); - } + chooser.setDialogTitle(localization.getString("Library.ChooseLibraryFolder"));// "Choose library + // folder"); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setAcceptAllFileFilterUsed(false); + if (chooser.showOpenDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION) { + library = Library.getInstance(chooser.getSelectedFile().getAbsolutePath()); + btnRefreshLibrary.doClick(); + libraryPathLabel.setText("Path : " + library.getLibraryPath()); + } } }); mnNewMenu.add(changeLibraryPathMenuItem); + + JMenuItem importMenuItem = new JMenuItem(localization.getString("File.import")); + importMenuItem.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + chooser.setDialogTitle(localization.getString("Import.ChooseImportEntry")); + chooser.setMultiSelectionEnabled(true); + if (chooser.showOpenDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION) { + for (File f : chooser.getSelectedFiles()) { + if (f.isDirectory()) { + for (File toImport : f.listFiles()) { + library.tryToImport(toImport.toPath()); + } + } else { + library.tryToImport(f.toPath()); + } + } + btnRefreshLibrary.doClick(); + } + } + }); + mnNewMenu.add(importMenuItem); mntmNewMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.META_DOWN_MASK)); mnNewMenu.add(mntmNewMenuItem); - - + } - - // -class MyListDropHandler extends TransferHandler { - private static final long serialVersionUID = -6453689410470088604L; - - JList list; - - public MyListDropHandler(JList list) { - this.list = list; - } - - public boolean canImport(TransferHandler.TransferSupport support) { - if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { - return false; - } - JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); - return dl.getIndex() != -1; - } - - public boolean importData(TransferHandler.TransferSupport support) { - if (!canImport(support)) { - return false; - } - - Transferable transferable = support.getTransferable(); - Object indexString; - try { - indexString = (Object)transferable.getTransferData(DataFlavor.stringFlavor); - } catch (Exception e) { - return false; - } - - List indices = Arrays.stream(indexString.toString().split(",")).mapToInt(Integer::parseInt).boxed().toList();//.sorted(Collections.reverseOrder()).toList(); - JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); - final Integer dropTargetIndex = dl.getIndex(); - - int nbBeforeDropIndex = (int)indices.stream().filter( (v) -> v < dropTargetIndex.intValue() ).count(); - - List objects = new ArrayList(); - for(int index = indices.size() - 1; index >= 0; index-- ) { - objects.add(((DefaultListModel)list.getModel()).remove(indices.get(index))); - } - - int insertIndex = dropTargetIndex - nbBeforeDropIndex; - - for(int i = objects.size() - 1; i >= 0; i-- ) { - ((DefaultListModel)list.getModel()).add(insertIndex++, objects.get(i)); - - } - - return true; - } -} + class MyListDropHandler extends TransferHandler { + private static final long serialVersionUID = -6453689410470088604L; + + JList list; + + public MyListDropHandler(JList list) { + this.list = list; + } + + public boolean canImport(TransferHandler.TransferSupport support) { + if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { + return false; + } + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + return dl.getIndex() != -1; + } + + public boolean importData(TransferHandler.TransferSupport support) { + if (!canImport(support)) { + return false; + } + + Transferable transferable = support.getTransferable(); + Object indexString; + try { + indexString = (Object) transferable.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + return false; + } + + List indices = Arrays.stream(indexString.toString().split(",")).mapToInt(Integer::parseInt).boxed() + .toList();// .sorted(Collections.reverseOrder()).toList(); + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + final Integer dropTargetIndex = dl.getIndex(); + + int nbBeforeDropIndex = (int) indices.stream().filter((v) -> v < dropTargetIndex.intValue()).count(); + + List objects = new ArrayList(); + for (int index = indices.size() - 1; index >= 0; index--) { + objects.add(((DefaultListModel) list.getModel()).remove(indices.get(index))); + } + + int insertIndex = dropTargetIndex - nbBeforeDropIndex; + + for (int i = objects.size() - 1; i >= 0; i--) { + ((DefaultListModel) list.getModel()).add(insertIndex++, objects.get(i)); + + } + + return true; + } + } } diff --git a/studio-desktop/src/main/java/studio/JsonPackCell.java b/studio-desktop/src/main/java/studio/JsonPackCell.java index 94d943ae5..97746cc4f 100644 --- a/studio-desktop/src/main/java/studio/JsonPackCell.java +++ b/studio-desktop/src/main/java/studio/JsonPackCell.java @@ -7,6 +7,7 @@ import java.awt.GridBagLayout; import java.awt.Insets; import java.util.List; +import java.util.Locale; import java.util.concurrent.CompletableFuture; import javax.swing.DefaultListModel; @@ -29,6 +30,7 @@ class JsonPackCell implements ListCellRenderer, UIResource { private static final long serialVersionUID = -9095012373460466070L; + private transient String locale = Locale.getDefault().toLanguageTag().replace("-", "_"); private static final Border noBorder = UIManager.getBorder("List.cellNoFocusBorder"); private static final Border selectedAndFocusedBorder = UIManager.getBorder("List.focusSelectedCellHighlightBorder"); @@ -55,6 +57,7 @@ private JPanel initialize() { gbc_icon.insets = new Insets(5, 5, 0, 5); gbc_icon.gridx = 0; gbc_icon.gridy = 0; + icon.setMinimumSize(new Dimension(64,64)); res.add(icon, gbc_icon); JLabel title = new JLabel(); @@ -65,6 +68,7 @@ private JPanel initialize() { gbc_title.insets = new Insets(5, 5, 5, 5); gbc_title.gridx = 1; gbc_title.gridy = 0; + gbc_title.weightx = 0.5; res.add(title, gbc_title); JLabel subTitle = new JLabel(); @@ -153,49 +157,57 @@ public Component getListCellRendererComponent(JList list, Js - LocalizedInfos defaultLocalizedInfos = value.getLocalizedInfos().values().iterator().next(); + LocalizedInfos defaultLocalizedInfos = value.getLocalizedInfos().containsKey(locale) ? defaultLocalizedInfos = value.getLocalizedInfos().get(locale) : (!value.getLocalizedInfos().isEmpty() ? defaultLocalizedInfos = value.getLocalizedInfos().values().iterator().next() : null); + List components = List.of(res.getComponents()); - components.stream().filter( (c) -> "icon".equals(c.getName())).findFirst().ifPresent( ( c) -> { - if ( defaultLocalizedInfos.hasFetchImage() ) { - ((JLabel)c).setIcon(new ImageIcon(defaultLocalizedInfos.getThumbnail())); - } else { - - CompletableFuture.runAsync(() -> { - defaultLocalizedInfos.getThumbnail(); - DefaultListModel model = (DefaultListModel) list.getModel(); - model.setElementAt(value, index); - }); - } - - }); - //icon.setData(defaultLocalizedInfos); - +// if ( defaultLocalizedInfos != null ) { + + components.stream().filter( (c) -> "icon".equals(c.getName())).findFirst().ifPresent( ( c) -> { + if ( defaultLocalizedInfos != null && defaultLocalizedInfos.hasFetchImage() ) { + ((JLabel)c).setIcon(new ImageIcon(defaultLocalizedInfos.getThumbnail())); + } else { + + CompletableFuture.runAsync(() -> { + if ( defaultLocalizedInfos == null ) return; + defaultLocalizedInfos.getThumbnail(); + DefaultListModel model = (DefaultListModel) list.getModel(); + model.setElementAt(value, index); + }); + } + }); + +// } components.stream().filter( (c) -> "title".equals(c.getName())).findFirst().ifPresent( ( c) -> { String strTitle = value.getTitle(); - if ( strTitle == null ) strTitle = defaultLocalizedInfos.getTitle(); + if ( strTitle == null && defaultLocalizedInfos != null ) strTitle = defaultLocalizedInfos.getTitle(); ((JLabel)c).setText(strTitle); }); - //title.setText(strTitle); components.stream().filter( (c) -> "subtitle".equals(c.getName())).findFirst().ifPresent( ( c) -> { String strSubTitle = value.getSubtitle(); - if ( strSubTitle == null ) strSubTitle = defaultLocalizedInfos.getSubtitle(); + if ( strSubTitle == null && defaultLocalizedInfos != null ) strSubTitle = defaultLocalizedInfos.getSubtitle(); ((JLabel)c).setText(strSubTitle); }); components.stream().filter( (c) -> "age".equals(c.getName())).findFirst().ifPresent( ( c) -> { - String strAge = value.getAgeMax() == -1 ? "From " + value.getAgeMin() + " years": "From " + value.getAgeMin() + " to " + value.getAgeMax() + " years"; - ((JLabel)c).setText(strAge); + if ( !(value.getAgeMin() == 0 && value.getAgeMax() == 0) ) { + String strAge = value.getAgeMax() == -1 ? "From " + value.getAgeMin() + " years": "From " + value.getAgeMin() + " to " + value.getAgeMax() + " years"; + ((JLabel)c).setText(strAge); + } else { + ((JLabel)c).setText(""); + } }); components.stream().filter( (c) -> "size".equals(c.getName())).findFirst().ifPresent( ( c) -> { - String strAge = FileUtils.byteCountToDisplaySize(FileUtils.ONE_KB * value.getSize()); - ((JLabel)c).setText(strAge); + if ( value.getSize() != 0 ) { + String strSize = FileUtils.byteCountToDisplaySize(FileUtils.ONE_KB * value.getSize()); + ((JLabel)c).setText(strSize); + } else { + ((JLabel)c).setText(""); + } }); - //subTitle.setText(strSubTitle); - return res; } diff --git a/studio-desktop/src/main/java/studio/PlaceholderTextField.java b/studio-desktop/src/main/java/studio/PlaceholderTextField.java new file mode 100644 index 000000000..4c38275ef --- /dev/null +++ b/studio-desktop/src/main/java/studio/PlaceholderTextField.java @@ -0,0 +1,41 @@ +package studio; + +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; + +import javax.swing.JTextField; + +public class PlaceholderTextField extends JTextField { + + private static final long serialVersionUID = 7150729146333944077L; + + + private String placeHolder; + + + public String getPlaceHolder() { + return placeHolder; + } + + + public void setPlaceHolder(String placeHolder) { + this.placeHolder = placeHolder; + } + + @Override + protected void paintComponent(Graphics g) { + super.paintComponent(g); + + if (placeHolder == null || placeHolder.length() == 0 || getText().length() > 0) { + return; + } + + final Graphics2D g2 = (Graphics2D) g; + g2.setRenderingHint( + RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2.setColor(getDisabledTextColor()); + g2.drawString(placeHolder, getInsets().left, g.getFontMetrics().getMaxAscent() + getInsets().top); + } +} diff --git a/studio-desktop/src/main/java/studio/database/JsonPack.java b/studio-desktop/src/main/java/studio/database/JsonPack.java index 55929e13f..3e92e30f1 100644 --- a/studio-desktop/src/main/java/studio/database/JsonPack.java +++ b/studio-desktop/src/main/java/studio/database/JsonPack.java @@ -2,13 +2,20 @@ import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import com.google.gson.annotations.SerializedName; public class JsonPack { + @Override + public boolean equals(Object obj) { + return obj instanceof JsonPack && uuid.equals(((JsonPack)obj).uuid); + } + @SerializedName("uuid") private String uuid; @@ -21,7 +28,6 @@ public class JsonPack { @SerializedName("creation_date") private Date creationDate; - @SerializedName("slug") private String slug; @@ -56,13 +62,12 @@ public class JsonPack { private Map tellers; @SerializedName("localized_infos") - private Map localizedInfos; + private Map localizedInfos = new HashMap<>(); @SerializedName("size") private long size; - public long getSize() { return size; } @@ -134,4 +139,12 @@ public Collection getTellers() { public Map getLocalizedInfos() { return localizedInfos; } + + + public String getResolvedTitle(Locale l) { + String locale = l.toLanguageTag().replace("-", "_"); + return getTitle() != null ? getTitle() : + getLocalizedInfos().get(locale) != null ? localizedInfos.get(locale).getTitle() : + localizedInfos.values().isEmpty() ? localizedInfos.values().iterator().next().getTitle() : ""; + } } \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/database/Library.java b/studio-desktop/src/main/java/studio/database/Library.java index 8c83511f6..fc044a2f6 100644 --- a/studio-desktop/src/main/java/studio/database/Library.java +++ b/studio-desktop/src/main/java/studio/database/Library.java @@ -1,6 +1,8 @@ package studio.database; +import java.io.File; import java.io.FileInputStream; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -14,8 +16,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; import java.util.List; +import java.util.Locale; import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.concurrent.CompletableFuture; @@ -28,10 +34,13 @@ import com.google.gson.JsonParseException; import com.google.gson.annotations.SerializedName; +import studio.core.v1.model.StoryPack; import studio.core.v1.model.metadata.StoryPackMetadata; import studio.core.v1.reader.archive.ArchiveStoryPackReader; import studio.core.v1.reader.binary.BinaryStoryPackReader; import studio.core.v1.reader.fs.FsStoryPackReader; +import studio.core.v1.utils.PackAssetsCompression; +import studio.core.v1.writer.fs.FsStoryPackWriter; public class Library { @@ -39,7 +48,9 @@ public class Library { public static final String DATABASE_URL = "https://server-data-prod.lunii.com/v2/packs"; public static final String RESOURCE_URL = "https://storage.googleapis.com/lunii-data-prod"; - private JsonResponse officalPacksDatabase; + private JsonResponse packsDatabase; + + private JsonResponse localDatabase; private static volatile Library instance; @@ -58,8 +69,11 @@ public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationConte } }); + builder.setPrettyPrinting(); + gson = builder.create(); + } public static Library getInstance(String path) { if (instance != null && instance.libraryPath.equals(path)) { @@ -74,8 +88,10 @@ public static Library getInstance(String path) { } private Library(String path) { - officalPacksDatabase = null; + packsDatabase = null; this.libraryPath = path; + localDatabase = new JsonResponse(); + localDatabase.packs = new HashMap<>(); } public String getLibraryPath() { @@ -96,6 +112,18 @@ public String getFolderForUUID(String uuid) { return null; } + + private JsonPack fromEnrichedData(StoryPackMetadata metaData) { + JsonObject obj = new JsonObject(); + + + obj.addProperty("title", metaData.getTitle()); + obj.addProperty("description", metaData.getDescription()); + obj.addProperty("uuid", metaData.getUuid()); + obj.addProperty("version", metaData.getVersion()); + return gson.fromJson(obj, JsonPack.class); + } + private Optional readPackFile(Path path) { // Handle all file formats if (path.toString().endsWith(".zip")) { @@ -103,10 +131,11 @@ private Optional readPackFile(Path path) { System.out.println("Reading archive pack metadata in folder " + path.toString()); ArchiveStoryPackReader packReader = new ArchiveStoryPackReader(); StoryPackMetadata meta = packReader.readMetadata(fis); + if (meta != null) { System.out.println("Pack found for UUID " + meta.getUuid()); //return Optional.of(new LibraryPack(path, Files.getLastModifiedTime(path).toMillis() , meta)); - Optional res = officalPacksDatabase.getPacks().stream().filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); + Optional res = packsDatabase.getPacks().stream().filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); if ( !res.isPresent() ) { System.out.println("Package not found for UUID " + meta.getUuid()); } @@ -126,7 +155,7 @@ private Optional readPackFile(Path path) { StoryPackMetadata meta = packReader.readMetadata(fis); if ( meta != null && meta.getUuid() != null ) { System.out.println("Pack found for UUID " + meta.getUuid()); - Optional res = officalPacksDatabase.getPacks() + Optional res = packsDatabase.getPacks() .stream() .filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())) @@ -150,7 +179,7 @@ private Optional readPackFile(Path path) { StoryPackMetadata meta = packReader.readMetadata(path); if (meta != null) { System.out.println("Pack found for UUID " + meta.getUuid()); - Optional res = officalPacksDatabase.getPacks().stream().filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); + Optional res = packsDatabase.getPacks().stream().filter( (JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); if ( !res.isPresent() ) { System.out.println("Package not found for UUID " + meta.getUuid()); } @@ -172,15 +201,15 @@ private Optional readPackFile(Path path) { public CompletableFuture refreshDatabase() { - officalPacksDatabase = null; + packsDatabase = null; return getPacks(); } - public CompletableFuture fetchFromServer() { + public CompletableFuture loadDatabase() { return CompletableFuture.runAsync( () -> { - if ( officalPacksDatabase != null ) return; + if ( packsDatabase != null ) return; try { URL getToken = new URL(TOKEN_URL); InputStream stream = getToken.openStream(); @@ -193,9 +222,54 @@ public CompletableFuture fetchFromServer() { URLConnection connection = getDatabase.openConnection(); connection.addRequestProperty("X-AUTH-TOKEN", token); - officalPacksDatabase = gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonResponse.class); + packsDatabase = gson.fromJson(new InputStreamReader(connection.getInputStream()), JsonResponse.class); + System.out.println(); + System.out.println("Official database from Lunii server repo contains packages : "); + + String locale = Locale.getDefault().toLanguageTag().replaceAll("-", "_"); + packsDatabase.getPacks().stream().forEach( pack -> { + String packTitle; + if ( pack.getTitle() != null ) packTitle = pack.getTitle(); + else { + packTitle = pack.getLocalizedInfos().get(locale) != null ? pack.getLocalizedInfos().get(locale).getTitle() : null; + Iterator> it = pack.getLocalizedInfos().entrySet().iterator(); + while ( packTitle == null && it.hasNext() ) { + Entry entry = it.next(); + packTitle = entry.getValue().getTitle() + " - (" + entry.getKey() + ")"; + } + } + System.out.println(pack.getUuid() + " - " + packTitle); + }); - //System.out.println(officalPacksDatabase.getPacks().stream().map( (p) -> p.getUuid()).toList()); + try(FileInputStream fis = new FileInputStream(Path.of(this.libraryPath, "unofficials.json").toFile())) { + localDatabase = gson.fromJson(new InputStreamReader(fis), JsonResponse.class); + if (localDatabase == null || localDatabase.packs == null ) { + localDatabase = new JsonResponse(); + localDatabase.packs = new HashMap<>(); + } + + System.out.println("Unofficial database from Lunii server repo contains packages : "); + localDatabase.getPacks().stream().forEach( pack -> { + String packTitle; + if ( pack.getTitle() != null ) packTitle = pack.getTitle(); + else { + packTitle = pack.getLocalizedInfos().get(locale) != null ? pack.getLocalizedInfos().get(locale).getTitle() : null; + Iterator> it = pack.getLocalizedInfos().entrySet().iterator(); + while ( packTitle == null && it.hasNext() ) { + Entry entry = it.next(); + packTitle = entry.getValue().getTitle() + " - (" + entry.getKey() + ")"; + } + } + System.out.println(pack.getUuid() + " - " + packTitle); + }); + + localDatabase.packs.entrySet().forEach( (Entry entry) -> { + packsDatabase.packs.put(entry.getKey(), entry.getValue()); + }); + } catch(IOException e) { + e.printStackTrace(); + + } } catch(NullPointerException e) { e.printStackTrace(); } catch (MalformedURLException e) { @@ -209,18 +283,19 @@ public CompletableFuture fetchFromServer() { } public Optional getPackForUUID(String uuid) { - if ( officalPacksDatabase == null ) return null; - return officalPacksDatabase.getPacks().stream().filter( (pack) -> pack.getUuid().equalsIgnoreCase(uuid)).findAny(); + if ( packsDatabase == null ) return null; + return packsDatabase.getPacks().stream().filter( (pack) -> pack.getUuid().equalsIgnoreCase(uuid)).findAny(); } public CompletableFuture> getPacks() { - return fetchFromServer().thenComposeAsync( (Void v) -> { + return loadDatabase().thenComposeAsync( (Void v) -> { return CompletableFuture.supplyAsync(() -> { try { return Files.list(Paths.get(libraryPath)) .map( this::readPackFile ) .filter( Optional::isPresent ) .map( Optional::get ) + .sorted((o1, o2) -> o1.getResolvedTitle(Locale.getDefault()).compareTo(o2.getResolvedTitle(Locale.getDefault()))) .toList(); } catch (IOException e) { // TODO Auto-generated catch block @@ -242,4 +317,122 @@ public Collection getPacks() { } + + + public boolean tryToImport(Path path) { + if ( path.toString().endsWith(".zip") ) { + ArchiveStoryPackReader packReader = new ArchiveStoryPackReader(); + try(FileInputStream fis = new FileInputStream(path.toFile())) { + StoryPack pack = packReader.read(fis); + fis.close(); + + //StoryPack packWithPreparedAssets = PackAssetsCompression.withPreparedAssetsFirmware2dot4(pack); + + + Optional jsonPack = this.getPackForUUID(pack.getUuid()); + if ( jsonPack.isEmpty() ) { + String packTitle = pack.getEnriched() != null ? pack.getEnriched().getTitle().toLowerCase() : null; + if ( packTitle == null ) { + return false; + } + + jsonPack = this.packsDatabase.getPacks().parallelStream().filter( (final JsonPack p) ->{ + System.out.println("Current pack main title : " + p.getTitle()); + System.out.println("All titles :"); + String concat = p.getLocalizedInfos().values().stream().map((locinfo) -> locinfo.getTitle()).reduce( (val1, val2) -> val1 + ", " + val2).orElseGet(() -> ""); + System.out.println(concat); + //String concat = String.join("," , titles); + return + (p.getTitle() != null && p.getTitle().toLowerCase().contains(packTitle)) || + p.getLocalizedInfos().values().stream().anyMatch( (locInfo) -> { + return locInfo.getTitle() != null && locInfo.getTitle().toLowerCase().contains(packTitle); + }); + } +// + //p.getLocalizedInfos().entrySet().stream().anyMatch( (entry) -> entry.getValue().getTitle() != null && entry.getValue().toString().equalsIgnoreCase(pack.getEnriched().getTitle())) + + + ).findAny(); + } + if ( jsonPack.isPresent() ) { + pack.setUuid(jsonPack.get().getUuid()); + } else { + + try(FileInputStream fis2 = new FileInputStream(path.toFile())) { + StoryPackMetadata metaData = packReader.readMetadata(fis2); + JsonPack customJsonPack = fromEnrichedData(metaData); + String random = metaData.getUuid(); + this.localDatabase.packs.put(random, customJsonPack); + CompletableFuture.runAsync( () -> { + try { + File unofficialsFile = Path.of(this.libraryPath, "unofficials.json").toFile(); + FileWriter fileWriter = new FileWriter(unofficialsFile); + gson.toJson(this.localDatabase, fileWriter); + fileWriter.flush(); + fileWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + }); + this.packsDatabase.packs.put(random, customJsonPack); + }catch(Exception e) { + e.printStackTrace(); + } + } + + if ( Path.of(this.libraryPath, pack.getUuid()).toFile().exists() ) { + return false; + } + + //this.officalPacksDatabase.getPacks().stream().filter((JsonPack p) -> p.getUuid().equalsIgnoreCase(meta.getUuid())).findFirst(); + FsStoryPackWriter writer = new FsStoryPackWriter(); + + Path outputPath = Path.of(this.libraryPath, pack.getUuid()); + writer.write(pack, outputPath); + + + + return true; + + + } catch (Exception e) { + e.printStackTrace(); + } + } else if ( path.toString().endsWith(".pack") ) { + BinaryStoryPackReader packReader = new BinaryStoryPackReader(); + FileInputStream fis; + try { + fis = new FileInputStream(path.toFile()); + + StoryPack storyPack = packReader.read(fis); + fis.close(); + + // Prepare assets (RLE-encoded BMP, audio must already be MP3) + StoryPack packWithPreparedAssets = PackAssetsCompression.withPreparedAssetsFirmware2dot4(storyPack); + + FsStoryPackWriter writer = new FsStoryPackWriter(); + Path outputPath = Path.of(this.libraryPath, storyPack.getUuid()); + + writer.write(packWithPreparedAssets, outputPath); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + + } else if ( Files.isDirectory(path) ) { + FsStoryPackReader packReader = new FsStoryPackReader(); + StoryPack pack; + try { + pack = packReader.read(path); + Path outputPath = Path.of(this.libraryPath, pack.getUuid()); + Files.move(path, outputPath); + return true; + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + return false; + + } } diff --git a/studio-desktop/src/main/java/studio/database/LocalizedInfos.java b/studio-desktop/src/main/java/studio/database/LocalizedInfos.java index 0203deb45..948f11742 100644 --- a/studio-desktop/src/main/java/studio/database/LocalizedInfos.java +++ b/studio-desktop/src/main/java/studio/database/LocalizedInfos.java @@ -18,7 +18,7 @@ public String getUrl() { } } - + @SerializedName("description") private String description; diff --git a/studio-desktop/src/main/java/studio/localization/Translation.properties b/studio-desktop/src/main/java/studio/localization/Translation.properties index 4cefa19c6..211d6d12a 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation.properties @@ -10,6 +10,8 @@ Device.list=Device Device.validate=Commit Device.refresh=Refresh Device.cancel=Cancel +Device.search=Search +Transfer.notransfer=No transfer Transfering.transferringpack=Transferring pack {} Transfering.deletingpack=Deleting pack {} Transfering.reordering=Ordering packs @@ -17,7 +19,11 @@ Transfering.done=Done Transfer.globalProgress=Progress Library.list=List Library.refresh=Refresh library +Library.filteronlynotpresentonbox=Only not present File.title=File +File.import=Import... File.quit=Quit +Library.search=Search Library.changePath=Change library path... -Library.ChooseLibraryFolder=Choose file \ No newline at end of file +Library.ChooseLibraryFolder=Choose file +Import.ChooseImportEntry=Choose file or folder \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties index 301c4c91f..b3c862c9b 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties @@ -10,6 +10,8 @@ Device.list=Boite lunii Device.validate=Valider Device.refresh=Rafraichir Device.cancel=Annuler +Device.search=Rechercher +Transfer.notransfer=Aucun transfert Transfering.transferringpack=Transfert du pack {} Transfering.deletingpack=Suppression du pack {} Transfering.reordering=Tri des packs @@ -17,7 +19,11 @@ Transfering.done=Termin Transfer.globalProgress=Progression Library.list=Liste Library.refresh=Rafraichir la librairie +Library.filteronlynotpresentonbox=Seulement non présent File.title=Fichier +File.import=Importer... File.quit=Quitter +Library.search=Rechercher Library.changePath=Changer le répertoire de la librairie... -Library.ChooseLibraryFolder=Choisir le répertoire \ No newline at end of file +Library.ChooseLibraryFolder=Choisir le répertoire +Import.ChooseImportEntry=Choisissez un fichier ou répertoire... \ No newline at end of file diff --git a/studio-desktop/src/main/resources/studio.sh b/studio-desktop/src/main/resources/studio.sh index b7c9bb7f9..f8d797f40 100755 --- a/studio-desktop/src/main/resources/studio.sh +++ b/studio-desktop/src/main/resources/studio.sh @@ -4,4 +4,4 @@ APP_PATH=`dirname $0` VERSION=studio-desktop-0.3.2-SNAPSHOT STUDIO_CP=$APP_PATH/lib/*:$APP_PATH:$APP_PATH/$VERSION.jar -java -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI \ No newline at end of file +java -Xdock:description="Studio" -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI \ No newline at end of file From 7209cb7aed15277f30cf4baae598c65d273d3fdf Mon Sep 17 00:00:00 2001 From: Horfee Date: Fri, 16 Jun 2023 14:34:25 +0200 Subject: [PATCH 06/21] small cleanup --- studio-desktop/src/main/java/studio/GUI.java | 34 ++++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index a839b87d4..13f684b06 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -200,9 +200,7 @@ private CompletableFuture> loadPacksFromDevice() { } } - private void initializeLunii() { - - Locale l = Locale.getDefault(); + private void initializeLunii() { library = Library.getInstance(System.getProperty("user.home")); libraryPathLabel.setText("Path: " + library.getLibraryPath()); @@ -551,7 +549,7 @@ public void contentsChanged(ListDataEvent e) { JSplitPane splitPane = new JSplitPane(); splitPane.setResizeWeight(0.5); panel.add(splitPane, BorderLayout.CENTER); - // panel_7.add(splitPane, gbc_splitPane); + JPanel deviceListPanel = new JPanel(); splitPane.setLeftComponent(deviceListPanel); @@ -1040,7 +1038,7 @@ public void onComplete(TransferStatus status) { } }); - btnRefresh = new JButton(localization.getString("Device.refresh"));// "Refresh from device"); + btnRefresh = new JButton(localization.getString("Device.refresh")); btnRefresh.setEnabled(false); GridBagConstraints gbc_btnRefersh = new GridBagConstraints(); gbc_btnRefersh.anchor = GridBagConstraints.NORTHWEST; @@ -1152,7 +1150,6 @@ public void keyTyped(KeyEvent e) { ds.createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); libraryPacksList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - // TransferHandler transferHandler = libraryPacksList.getTransferHandler(); JPanel panel_6 = new JPanel(); libraryListPanel.add(panel_6, BorderLayout.SOUTH); @@ -1161,7 +1158,7 @@ public void keyTyped(KeyEvent e) { panel_6.setLayout(gbl_panel_6); panel_6.setMinimumSize(new Dimension(100, 100)); - btnRefreshLibrary = new JButton(localization.getString("Library.refresh"));// "Refresh library"); + btnRefreshLibrary = new JButton(localization.getString("Library.refresh")); btnRefreshLibrary.setEnabled(false); GridBagConstraints gbc_btnRefreshLibrary = new GridBagConstraints(); gbc_btnRefreshLibrary.anchor = GridBagConstraints.NORTHWEST; @@ -1246,16 +1243,6 @@ public void keyTyped(KeyEvent e) { } }); -// JPanel panel_7 = new JPanel(); -// panel_7.setBorder(null); -// panel.add(panel_7, BorderLayout.CENTER); -// GridBagLayout gbl_panel_7 = new GridBagLayout(); -// gbl_panel_7.columnWidths = new int[]{0, 0}; -// gbl_panel_7.rowHeights = new int[]{0, 0}; -// gbl_panel_7.columnWeights = new double[]{1.0, Double.MIN_VALUE}; -// gbl_panel_7.rowWeights = new double[]{1.0, Double.MIN_VALUE}; -// panel_7.setLayout(gbl_panel_7); - statusPanel = new JPanel(); panel.add(statusPanel, BorderLayout.SOUTH); statusLayout = new GridBagLayout(); @@ -1316,15 +1303,14 @@ public void actionPerformed(ActionEvent e) { } }); - JMenuItem changeLibraryPathMenuItem = new JMenuItem(localization.getString("Library.changePath"));// "Change - // library - // path..."); + JMenuItem changeLibraryPathMenuItem = new JMenuItem(localization.getString("Library.changePath")); + changeLibraryPathMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { JFileChooser chooser = new JFileChooser(); chooser.setCurrentDirectory(new java.io.File(library.getLibraryPath())); - chooser.setDialogTitle(localization.getString("Library.ChooseLibraryFolder"));// "Choose library - // folder"); + chooser.setDialogTitle(localization.getString("Library.ChooseLibraryFolder")); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setAcceptAllFileFilterUsed(false); if (chooser.showOpenDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION) { @@ -1362,7 +1348,6 @@ public void actionPerformed(ActionEvent e) { } -// class MyListDropHandler extends TransferHandler { private static final long serialVersionUID = -6453689410470088604L; @@ -1394,8 +1379,7 @@ public boolean importData(TransferHandler.TransferSupport support) { return false; } - List indices = Arrays.stream(indexString.toString().split(",")).mapToInt(Integer::parseInt).boxed() - .toList();// .sorted(Collections.reverseOrder()).toList(); + List indices = Arrays.stream(indexString.toString().split(",")).mapToInt(Integer::parseInt).boxed().toList(); JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); final Integer dropTargetIndex = dl.getIndex(); From 8f688a1e8872e8c4a00396f7e60988366bb915f3 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 22 Jun 2023 11:41:32 +0200 Subject: [PATCH 07/21] Fix drag and drop issue --- .../studio/DeviceListTransferHandler.java | 104 ++++++++++++++++++ studio-desktop/src/main/java/studio/GUI.java | 100 +++-------------- .../src/main/java/studio/JsonPackCell.java | 2 +- 3 files changed, 118 insertions(+), 88 deletions(-) create mode 100644 studio-desktop/src/main/java/studio/DeviceListTransferHandler.java diff --git a/studio-desktop/src/main/java/studio/DeviceListTransferHandler.java b/studio-desktop/src/main/java/studio/DeviceListTransferHandler.java new file mode 100644 index 000000000..4e0347e4f --- /dev/null +++ b/studio-desktop/src/main/java/studio/DeviceListTransferHandler.java @@ -0,0 +1,104 @@ +package studio; + +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.IntStream; + +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.TransferHandler; + +import studio.database.JsonPack; + +public class DeviceListTransferHandler extends TransferHandler { + + private JList libraryPacksList; + private JList devicePacksList; + + public DeviceListTransferHandler(JList libraryList, JList deviceList) { + super(); + this.libraryPacksList = libraryList; + this.devicePacksList = deviceList; + } + + private static final long serialVersionUID = -6050701764610620507L; + + public boolean canImport(TransferHandler.TransferSupport support) { + if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { + return false; + } + if (!support.getComponent().getName().equals("devices")) { + return false; + } + + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + return dl.getIndex() != -1; + } + + public boolean importData(TransferHandler.TransferSupport support) { + if (!canImport(support)) { + return false; + } + + Transferable transferable = support.getTransferable(); + String transferMe; + try { + transferMe = (String) transferable.getTransferData(DataFlavor.stringFlavor); + } catch (UnsupportedFlavorException | IOException e) { + e.printStackTrace(); + return false; + } + + String source = transferMe.substring(0, transferMe.indexOf(": ")); + List uuids = List.of(transferMe.substring(transferMe.indexOf(": ") + 2).split(",")); + + JList list = source.equals("library") ? libraryPacksList + : source.equals("devices") ? devicePacksList : null; + if (list == null) + return false; + + final DefaultListModel model = ((DefaultListModel) list.getModel()); + + List indices = new ArrayList(); + for (String uuid : uuids) { + indices.add(IntStream.range(0, model.getSize()).filter(i -> uuid.equals(model.get(i).getUuid())) + .findFirst().getAsInt()); + } + + JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); + final Integer dropTargetIndex = dl.getIndex(); + + if (source.equals("devices")) { + int nbBeforeDropIndex = (int) indices.stream().filter((v) -> v < dropTargetIndex.intValue()) + .count(); + List objects = new ArrayList(); + for (int index = indices.size() - 1; index >= 0; index--) { + objects.add(model.remove(indices.get(index))); + } + + int insertIndex = dropTargetIndex - nbBeforeDropIndex; + + for (int i = objects.size() - 1; i >= 0; i--) { + model.add(insertIndex++, objects.get(i)); + + } + } else { + List existingPacks = List + .of(((DefaultListModel) ((JList) support.getComponent()).getModel()) + .toArray()); + List existingUUIDs = existingPacks.stream().map(p -> ((JsonPack) p).getUuid()).toList(); + + List toAdd = indices.stream().map(i -> model.get(i)) + .filter(pack -> existingUUIDs.stream().allMatch(s -> !s.equalsIgnoreCase(pack.getUuid()))) + .toList(); + ((DefaultListModel) devicePacksList.getModel()).addAll(dropTargetIndex, toAdd); + } + + return true; + } + +} diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index 13f684b06..cbd380f07 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -209,7 +209,7 @@ private void initializeLunii() { btnRefreshLibrary.setEnabled(true); }); - fsDriver = new FsStoryTellerAsyncDriver(true); + fsDriver = new FsStoryTellerAsyncDriver(false); rawDriver = new RawStoryTellerAsyncDriver(); fsDriver.registerDeviceListener(new DeviceHotplugEventListener() { @@ -481,21 +481,24 @@ private void initialize() { devicePacksModel = new DefaultListModel(); - DragSource ds = new DragSource(); + DragGestureListener dgl = new DragGestureListener() { @Override public void dragGestureRecognized(DragGestureEvent dge) { String source = dge.getComponent().getName(); + System.out.println("Recognized"); if (source.equals("devices") || source.equals("library")) { String selectedIndices = ((JList) dge.getComponent()).getSelectedValuesList().stream() .map(JsonPack::getUuid).collect(Collectors.joining(",")); StringSelection transferable = new StringSelection(source + ": " + selectedIndices); - ds.startDrag(dge, DragSource.DefaultCopyDrop, transferable, null); + System.out.println("start drag"); + dge.getDragSource().startDrag(dge, DragSource.DefaultMoveDrop, transferable, null); } } }; + DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); libraryPacksModel = new DefaultListModel(); devicePacksModel.addListDataListener(new ListDataListener() { @@ -605,7 +608,7 @@ public void keyTyped(KeyEvent e) { devicePacksList.setCellRenderer(new JsonPackCell()); devicePacksList.setName("devices"); devicePacksScrollPane.setViewportView(devicePacksList); - devicePacksList.setDragEnabled(true); + //devicePacksList.setDragEnabled(true); devicePacksList.setDropMode(DropMode.INSERT); devicePacksList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { @@ -617,87 +620,8 @@ public void valueChanged(ListSelectionEvent e) { } }); - ds.createDefaultDragGestureRecognizer(devicePacksList, DnDConstants.ACTION_MOVE, dgl); - devicePacksList.setTransferHandler(new TransferHandler() { - - private static final long serialVersionUID = -6050701764610620507L; - - public boolean canImport(TransferHandler.TransferSupport support) { - if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) { - return false; - } - if (!support.getComponent().getName().equals("devices")) { - return false; - } - - JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); - return dl.getIndex() != -1; - } - - public boolean importData(TransferHandler.TransferSupport support) { - if (!canImport(support)) { - return false; - } - - Transferable transferable = support.getTransferable(); - String transferMe; - try { - transferMe = (String) transferable.getTransferData(DataFlavor.stringFlavor); - } catch (UnsupportedFlavorException | IOException e) { - e.printStackTrace(); - return false; - } - - String source = transferMe.substring(0, transferMe.indexOf(": ")); - List uuids = List.of(transferMe.substring(transferMe.indexOf(": ") + 2).split(",")); - - JList list = source.equals("library") ? libraryPacksList - : source.equals("devices") ? devicePacksList : null; - if (list == null) - return false; - - final DefaultListModel model = ((DefaultListModel) list.getModel()); - - List indices = new ArrayList(); - for (String uuid : uuids) { - indices.add(IntStream.range(0, model.getSize()).filter(i -> uuid.equals(model.get(i).getUuid())) - .findFirst().getAsInt()); - } - - JList.DropLocation dl = (JList.DropLocation) support.getDropLocation(); - final Integer dropTargetIndex = dl.getIndex(); - - if (source.equals("devices")) { - int nbBeforeDropIndex = (int) indices.stream().filter((v) -> v < dropTargetIndex.intValue()) - .count(); - List objects = new ArrayList(); - for (int index = indices.size() - 1; index >= 0; index--) { - objects.add(model.remove(indices.get(index))); - } - - int insertIndex = dropTargetIndex - nbBeforeDropIndex; - - for (int i = objects.size() - 1; i >= 0; i--) { - model.add(insertIndex++, objects.get(i)); - - } - } else { - List existingPacks = List - .of(((DefaultListModel) ((JList) support.getComponent()).getModel()) - .toArray()); - List existingUUIDs = existingPacks.stream().map(p -> ((JsonPack) p).getUuid()).toList(); - - List toAdd = indices.stream().map(i -> model.get(i)) - .filter(pack -> existingUUIDs.stream().allMatch(s -> !s.equalsIgnoreCase(pack.getUuid()))) - .toList(); - devicePacksModel.addAll(dropTargetIndex, toAdd); - } - - return true; - } - - }); - + DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(devicePacksList, DnDConstants.ACTION_MOVE, dgl); + JPanel panel_4 = new JPanel(); deviceListPanel.add(panel_4, BorderLayout.SOUTH); GridBagLayout gbl_panel_4 = new GridBagLayout(); @@ -1100,10 +1024,12 @@ public void actionPerformed(ActionEvent e) { JScrollPane libraryPacksScrollPane = new JScrollPane(); libraryListPanel.add(libraryPacksScrollPane); libraryPacksList = new JList(libraryPacksModel); + devicePacksList.setTransferHandler(new DeviceListTransferHandler(libraryPacksList, devicePacksList)); + libraryPacksScrollPane.setViewportView(libraryPacksList); libraryPacksList.setName("library"); libraryPacksList.setCellRenderer(new JsonPackCell()); - libraryPacksList.setDragEnabled(true); + //libraryPacksList.setDragEnabled(true); libraryPacksList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { JList list = (JList) evt.getSource(); @@ -1147,7 +1073,7 @@ public void keyTyped(KeyEvent e) { } }); - ds.createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); + DragSource.getDefaultDragSource().createDefaultDragGestureRecognizer(libraryPacksList, DnDConstants.ACTION_MOVE, dgl); libraryPacksList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); diff --git a/studio-desktop/src/main/java/studio/JsonPackCell.java b/studio-desktop/src/main/java/studio/JsonPackCell.java index 97746cc4f..087e6db9a 100644 --- a/studio-desktop/src/main/java/studio/JsonPackCell.java +++ b/studio-desktop/src/main/java/studio/JsonPackCell.java @@ -157,7 +157,7 @@ public Component getListCellRendererComponent(JList list, Js - LocalizedInfos defaultLocalizedInfos = value.getLocalizedInfos().containsKey(locale) ? defaultLocalizedInfos = value.getLocalizedInfos().get(locale) : (!value.getLocalizedInfos().isEmpty() ? defaultLocalizedInfos = value.getLocalizedInfos().values().iterator().next() : null); + final LocalizedInfos defaultLocalizedInfos = value.getLocalizedInfos().containsKey(locale) ? value.getLocalizedInfos().get(locale) : (!value.getLocalizedInfos().isEmpty() ? value.getLocalizedInfos().values().iterator().next() : null); List components = List.of(res.getComponents()); From 0f9c99333e4ff97f3f2963d9c7545a2c12493f12 Mon Sep 17 00:00:00 2001 From: Horfee Date: Fri, 14 Jul 2023 16:09:50 +0200 Subject: [PATCH 08/21] adding capacity to export to excel --- pom.xml | 4 +- studio-desktop/pom.xml | 32 +++- studio-desktop/src/main/java/studio/GUI.java | 176 +++++++++++++++++- .../main/java/studio/database/Library.java | 5 + .../localization/Translation.properties | 7 +- .../localization/Translation_fr_FR.properties | 7 +- 6 files changed, 223 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index c2cd2f7e4..87e4fd608 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,7 @@ core driver metadata - web-ui + studio-desktop @@ -49,7 +49,7 @@ commons-io commons-io - 2.6 + 2.13.0 commons-codec diff --git a/studio-desktop/pom.xml b/studio-desktop/pom.xml index 35a44d206..afabdddef 100644 --- a/studio-desktop/pom.xml +++ b/studio-desktop/pom.xml @@ -5,22 +5,23 @@ 0.3.2-SNAPSHOT 4.0.0 + 0.3.3-SNAPSHOT studio-desktop studio studio-core - ${project.version} + ${project.parent.version} studio studio-metadata - ${project.version} + ${project.parent.version} studio studio-driver - ${project.version} + ${project.parent.version} com.google.code.gson @@ -75,6 +76,31 @@ log4j-jul 2.13.2 + + org.apache.poi + poi + 5.2.3 + + + org.apache.poi + poi-ooxml + 5.2.3 + + + org.jxls + jxls-jexcel + 1.0.9 + + + org.dhatim + fastexcel-reader + 0.15.3 + + + org.dhatim + fastexcel + 0.15.3 + diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index cbd380f07..b77fc6684 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -13,7 +13,6 @@ import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.StringSelection; import java.awt.datatransfer.Transferable; -import java.awt.datatransfer.UnsupportedFlavorException; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; @@ -27,6 +26,8 @@ import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; @@ -34,6 +35,7 @@ import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.Optional; @@ -73,6 +75,17 @@ import javax.swing.event.ListSelectionListener; import org.apache.commons.io.FileUtils; +import org.apache.poi.common.usermodel.HyperlinkType; +import org.apache.poi.ss.usermodel.CellStyle; +import org.apache.poi.ss.usermodel.FillPatternType; +import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.util.CellRangeAddress; +import org.apache.poi.xssf.usermodel.XSSFCell; +import org.apache.poi.xssf.usermodel.XSSFFont; +import org.apache.poi.xssf.usermodel.XSSFHyperlink; +import org.apache.poi.xssf.usermodel.XSSFRow; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.usb4java.Device; import studio.database.JsonPack; @@ -1269,6 +1282,167 @@ public void actionPerformed(ActionEvent e) { } }); mnNewMenu.add(importMenuItem); + + JMenuItem exportMenuItem = new JMenuItem(localization.getString("File.export")); + exportMenuItem.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + JFileChooser chooser = new JFileChooser(); + chooser.setDialogTitle(localization.getString("Export.SaveFile")); + chooser.setMultiSelectionEnabled(true); + chooser.setAcceptAllFileFilterUsed(false); + + if (chooser.showSaveDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION) { + int response = JOptionPane.showConfirmDialog(frmLuniiTransfer, "Export entire library ?", "Export library", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE); + if ( response == JOptionPane.CANCEL_OPTION ) { + return; + } + + List data = new ArrayList<>(); + List downloadedLibrary = Collections.list(libraryPacksModel.elements()).stream().map( (JsonPack pack) -> pack.getUuid()).toList(); + List downloadedOnDevice = Collections.list(devicePacksModel.elements()).stream().map( (JsonPack pack) -> pack.getUuid()).toList(); + + if ( response == JOptionPane.YES_OPTION ) { + try { + data = library.getAllLuniiPacks().get(); + } catch (InterruptedException | ExecutionException e1) { + e1.printStackTrace(); + return; + } + } else if ( response == JOptionPane.NO_OPTION ) { + data = Collections.list(libraryPacksModel.elements()); + + } + + XSSFWorkbook workbook = new XSSFWorkbook(); + XSSFSheet sheet = workbook.createSheet("Library"); +// sheet.setColumnWidth(0, 6000); +// sheet.setColumnWidth(1, 4000); + + XSSFRow header = sheet.createRow(0); + + CellStyle headerStyle = workbook.createCellStyle(); + headerStyle.setFillForegroundColor(IndexedColors.LIGHT_BLUE.getIndex()); + headerStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND); + + XSSFFont font = ((XSSFWorkbook) workbook).createFont(); + font.setFontName("Arial"); + font.setFontHeightInPoints((short) 16); + font.setBold(true); + headerStyle.setFont(font); + + XSSFCell headerCell = header.createCell(0); + headerCell.setCellValue("Ref"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(1); + headerCell.setCellValue("Title"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(2); + headerCell.setCellValue("Age - From"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(3); + headerCell.setCellValue("Age - To"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(4); + headerCell.setCellValue("Link"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(5); + headerCell.setCellValue("Downloaded"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(6); + headerCell.setCellValue("Present on the device"); + headerCell.setCellStyle(headerStyle); + + headerCell = header.createCell(7); + headerCell.setCellValue("Locale"); + headerCell.setCellStyle(headerStyle); + + sheet.setAutoFilter(new CellRangeAddress(0,0,0,7)); + + Locale locale = Locale.getDefault(); + data.forEach( (JsonPack pack) -> { + XSSFRow dataRow = sheet.createRow(sheet.getLastRowNum() + 1); + XSSFCell dataCell = dataRow.createCell(0); + dataCell.setCellValue(pack.getUuid()); + String usedLocale = locale.getDisplayLanguage(); + + dataCell = dataRow.createCell(1); + String title = pack.getTitle(); + if ( title == null || title.length() == 0 ) { + title = pack.getResolvedTitle(locale); + if ( title == null || title.length() == 0 ) { + usedLocale = pack.getLocalizedInfos().keySet().iterator().next().replace("_", "-"); + title = pack.getResolvedTitle(Locale.forLanguageTag(usedLocale)); + usedLocale = Locale.forLanguageTag(usedLocale).getDisplayLanguage(); + + } + } + dataCell.setCellValue(title); + + dataCell = dataRow.createCell(2); + if ( pack.getAgeMin() != -1 ) { + dataCell.setCellValue(pack.getAgeMin()); + } + + dataCell = dataRow.createCell(3); + if ( pack.getAgeMax() != -1 ) { + dataCell.setCellValue(pack.getAgeMax()); + } + + dataCell = dataRow.createCell(4); + String url = "https://lunii.com/" + locale.getCountry().toLowerCase() + "-" + locale.getLanguage() + "/luniistore-catalogue/" + pack.getSlug(); + XSSFHyperlink link = (XSSFHyperlink)workbook.getCreationHelper().createHyperlink(HyperlinkType.URL); + link.setAddress(url); + dataCell.setCellValue(url); + dataCell.setHyperlink((XSSFHyperlink) link); + + + dataCell = dataRow.createCell(5); + dataCell.setCellValue(downloadedLibrary.contains(pack.getUuid())); + + dataCell = dataRow.createCell(6); + dataCell.setCellValue(downloadedOnDevice.contains(pack.getUuid())); + + dataCell = dataRow.createCell(7); + dataCell.setCellValue(usedLocale); + + }); + + for(int i = 0; i < sheet.getRow(0).getLastCellNum(); i++) { + sheet.autoSizeColumn(i); + } + + FileOutputStream fos; + try { + fos = new FileOutputStream(chooser.getSelectedFile()); + workbook.write(fos); + fos.close(); + } catch (FileNotFoundException e1) { + e1.printStackTrace(); + } catch (IOException e1) { + e1.printStackTrace(); + } finally { + try { + workbook.close(); + } catch (IOException e1) { + e1.printStackTrace(); + } + } + + + } + + } + + }); + mnNewMenu.add(exportMenuItem); mntmNewMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, InputEvent.META_DOWN_MASK)); mnNewMenu.add(mntmNewMenuItem); diff --git a/studio-desktop/src/main/java/studio/database/Library.java b/studio-desktop/src/main/java/studio/database/Library.java index fc044a2f6..0d8dd610e 100644 --- a/studio-desktop/src/main/java/studio/database/Library.java +++ b/studio-desktop/src/main/java/studio/database/Library.java @@ -287,6 +287,11 @@ public Optional getPackForUUID(String uuid) { return packsDatabase.getPacks().stream().filter( (pack) -> pack.getUuid().equalsIgnoreCase(uuid)).findAny(); } + + public CompletableFuture> getAllLuniiPacks() { + return loadDatabase().thenComposeAsync( (Void v) -> CompletableFuture.supplyAsync( () -> packsDatabase.getPacks().stream().toList())); + } + public CompletableFuture> getPacks() { return loadDatabase().thenComposeAsync( (Void v) -> { return CompletableFuture.supplyAsync(() -> { diff --git a/studio-desktop/src/main/java/studio/localization/Translation.properties b/studio-desktop/src/main/java/studio/localization/Translation.properties index 211d6d12a..64cb2fb4d 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation.properties @@ -23,7 +23,12 @@ Library.filteronlynotpresentonbox=Only not present File.title=File File.import=Import... File.quit=Quit +File.export=Export... +Export.SaveFile=Save file Library.search=Search Library.changePath=Change library path... Library.ChooseLibraryFolder=Choose file -Import.ChooseImportEntry=Choose file or folder \ No newline at end of file +Import.ChooseImportEntry=Choose file or folder +JsonPackCell.age1=From {} years +JsonPackCell.age2=To {} years +JsonPackCell.age3=From {} to {} years \ No newline at end of file diff --git a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties index b3c862c9b..2fff3ae6a 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties @@ -23,7 +23,12 @@ Library.filteronlynotpresentonbox=Seulement non pr File.title=Fichier File.import=Importer... File.quit=Quitter +File.export=Exporter... +Export.SaveFile=Sauvegarder le fichier Library.search=Rechercher Library.changePath=Changer le répertoire de la librairie... Library.ChooseLibraryFolder=Choisir le répertoire -Import.ChooseImportEntry=Choisissez un fichier ou répertoire... \ No newline at end of file +Import.ChooseImportEntry=Choisissez un fichier ou répertoire... +JsonPackCell.age1=À partir de {} ans +JsonPackCell.age2=Jusqu'à {} ans +JsonPackCell.age3=De {} à {} ans \ No newline at end of file From f510de2d392f10f8a1939d9c1a1e83566e0c1fca Mon Sep 17 00:00:00 2001 From: Horfee Date: Fri, 14 Jul 2023 16:12:49 +0200 Subject: [PATCH 09/21] fix start script --- studio-desktop/src/main/resources/studio.sh | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/studio-desktop/src/main/resources/studio.sh b/studio-desktop/src/main/resources/studio.sh index f8d797f40..3665c79bb 100755 --- a/studio-desktop/src/main/resources/studio.sh +++ b/studio-desktop/src/main/resources/studio.sh @@ -1,7 +1,12 @@ #/bin/bash APP_PATH=`dirname $0` -VERSION=studio-desktop-0.3.2-SNAPSHOT +VERSION=studio-desktop-0.3.3-SNAPSHOT STUDIO_CP=$APP_PATH/lib/*:$APP_PATH:$APP_PATH/$VERSION.jar -java -Xdock:description="Studio" -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI \ No newline at end of file +if [ "$(uname)" == "Darwin" ]; then + java -Xdock:description="Studio" -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI +else; then + java -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI +fi + From a9a95d31321520465b8aec7d5dfd47cd6f36753c Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 10:15:31 +0200 Subject: [PATCH 10/21] realignment of versioning --- studio-desktop/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/studio-desktop/pom.xml b/studio-desktop/pom.xml index afabdddef..6f88f55af 100644 --- a/studio-desktop/pom.xml +++ b/studio-desktop/pom.xml @@ -2,10 +2,10 @@ studio-parent studio - 0.3.2-SNAPSHOT + 0.4.1-SNAPSHOT 4.0.0 - 0.3.3-SNAPSHOT + 0.4.1-SNAPSHOT studio-desktop From 9c0e590202fa0bc49ca21b498f7b6ef9295c941d Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 10:15:41 +0200 Subject: [PATCH 11/21] fix launch script --- studio-desktop/src/main/resources/studio.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/studio-desktop/src/main/resources/studio.sh b/studio-desktop/src/main/resources/studio.sh index 3665c79bb..414198da1 100755 --- a/studio-desktop/src/main/resources/studio.sh +++ b/studio-desktop/src/main/resources/studio.sh @@ -1,12 +1,12 @@ -#/bin/bash +#!/bin/bash APP_PATH=`dirname $0` -VERSION=studio-desktop-0.3.3-SNAPSHOT +VERSION=${project.build.finalName} STUDIO_CP=$APP_PATH/lib/*:$APP_PATH:$APP_PATH/$VERSION.jar if [ "$(uname)" == "Darwin" ]; then java -Xdock:description="Studio" -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI -else; then +else java -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI fi From 15d88af770e302032ef2fb146fae111e7cb6fdd6 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 10:33:27 +0200 Subject: [PATCH 12/21] fixing a translation --- studio-desktop/src/main/java/studio/GUI.java | 4 ++-- .../src/main/java/studio/JsonPackCell.java | 19 ++++++++++++++++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index b77fc6684..92f888f56 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -618,7 +618,7 @@ public void keyTyped(KeyEvent e) { } } }); - devicePacksList.setCellRenderer(new JsonPackCell()); + devicePacksList.setCellRenderer(new JsonPackCell(localization)); devicePacksList.setName("devices"); devicePacksScrollPane.setViewportView(devicePacksList); //devicePacksList.setDragEnabled(true); @@ -1041,7 +1041,7 @@ public void actionPerformed(ActionEvent e) { libraryPacksScrollPane.setViewportView(libraryPacksList); libraryPacksList.setName("library"); - libraryPacksList.setCellRenderer(new JsonPackCell()); + libraryPacksList.setCellRenderer(new JsonPackCell(localization)); //libraryPacksList.setDragEnabled(true); libraryPacksList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent evt) { diff --git a/studio-desktop/src/main/java/studio/JsonPackCell.java b/studio-desktop/src/main/java/studio/JsonPackCell.java index 087e6db9a..abf9f77a1 100644 --- a/studio-desktop/src/main/java/studio/JsonPackCell.java +++ b/studio-desktop/src/main/java/studio/JsonPackCell.java @@ -6,8 +6,10 @@ import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; +import java.util.Arrays; import java.util.List; import java.util.Locale; +import java.util.ResourceBundle; import java.util.concurrent.CompletableFuture; import javax.swing.DefaultListModel; @@ -35,10 +37,13 @@ class JsonPackCell implements ListCellRenderer, UIResource { private static final Border noBorder = UIManager.getBorder("List.cellNoFocusBorder"); private static final Border selectedAndFocusedBorder = UIManager.getBorder("List.focusSelectedCellHighlightBorder"); private static final Border focusBorder = UIManager.getBorder("List.focusCellHighlightBorder"); - - JsonPackCell() { + + private ResourceBundle localization; + + JsonPackCell(ResourceBundle bundle) { super(); initialize(); + localization = bundle; } @@ -194,7 +199,7 @@ public Component getListCellRendererComponent(JList list, Js components.stream().filter( (c) -> "age".equals(c.getName())).findFirst().ifPresent( ( c) -> { if ( !(value.getAgeMin() == 0 && value.getAgeMax() == 0) ) { - String strAge = value.getAgeMax() == -1 ? "From " + value.getAgeMin() + " years": "From " + value.getAgeMin() + " to " + value.getAgeMax() + " years"; + String strAge = value.getAgeMax() == -1 ? substituteParameters(localization.getString("JsonPackCell.age1"), value.getAgeMin()) : substituteParameters(localization.getString("JsonPackCell.age3"), value.getAgeMin(), value.getAgeMax()); ((JLabel)c).setText(strAge); } else { ((JLabel)c).setText(""); @@ -211,5 +216,13 @@ public Component getListCellRendererComponent(JList list, Js return res; } + + private static String substituteParameters(String message, Object ... params) { + while(message.indexOf("{}") > -1 && params.length > 0 ) { + message = message.replaceFirst("\\{\\}", (params[0] != null ? params[0].toString() : "")); + params = Arrays.copyOfRange(params, 1, params.length); + } + return message; + } } \ No newline at end of file From 516f7e3486ad19d7a4b4af828157f89fbe73d37b Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 13:55:30 +0200 Subject: [PATCH 13/21] adding languages --- .../java/studio/LanguagesCellRenderer.java | 109 +++ .../src/main/java/studio/flags/ad.svg | 148 ++++ .../src/main/java/studio/flags/ae.svg | 6 + .../src/main/java/studio/flags/af.svg | 81 ++ .../src/main/java/studio/flags/ag.svg | 14 + .../src/main/java/studio/flags/ai.svg | 29 + .../src/main/java/studio/flags/al.svg | 5 + .../src/main/java/studio/flags/am.svg | 5 + .../src/main/java/studio/flags/ao.svg | 13 + .../src/main/java/studio/flags/aq.svg | 5 + .../src/main/java/studio/flags/ar.svg | 32 + .../src/main/java/studio/flags/arab.svg | 109 +++ .../src/main/java/studio/flags/as.svg | 73 ++ .../src/main/java/studio/flags/at.svg | 4 + .../src/main/java/studio/flags/au.svg | 8 + .../src/main/java/studio/flags/aw.svg | 186 +++++ .../src/main/java/studio/flags/ax.svg | 18 + .../src/main/java/studio/flags/az.svg | 8 + .../src/main/java/studio/flags/ba.svg | 12 + .../src/main/java/studio/flags/bb.svg | 6 + .../src/main/java/studio/flags/bd.svg | 4 + .../src/main/java/studio/flags/be.svg | 7 + .../src/main/java/studio/flags/bf.svg | 7 + .../src/main/java/studio/flags/bg.svg | 5 + .../src/main/java/studio/flags/bh.svg | 4 + .../src/main/java/studio/flags/bi.svg | 15 + .../src/main/java/studio/flags/bj.svg | 14 + .../src/main/java/studio/flags/bl.svg | 7 + .../src/main/java/studio/flags/bm.svg | 97 +++ .../src/main/java/studio/flags/bn.svg | 36 + .../src/main/java/studio/flags/bo.svg | 674 +++++++++++++++++ .../src/main/java/studio/flags/bq.svg | 5 + .../src/main/java/studio/flags/br.svg | 45 ++ .../src/main/java/studio/flags/bs.svg | 13 + .../src/main/java/studio/flags/bt.svg | 89 +++ .../src/main/java/studio/flags/bv.svg | 13 + .../src/main/java/studio/flags/bw.svg | 7 + .../src/main/java/studio/flags/by.svg | 18 + .../src/main/java/studio/flags/bz.svg | 145 ++++ .../src/main/java/studio/flags/ca.svg | 4 + .../src/main/java/studio/flags/cc.svg | 19 + .../src/main/java/studio/flags/cd.svg | 12 + .../src/main/java/studio/flags/cefta.svg | 13 + .../src/main/java/studio/flags/cf.svg | 15 + .../src/main/java/studio/flags/cg.svg | 12 + .../src/main/java/studio/flags/ch.svg | 9 + .../src/main/java/studio/flags/ci.svg | 7 + .../src/main/java/studio/flags/ck.svg | 9 + .../src/main/java/studio/flags/cl.svg | 13 + .../src/main/java/studio/flags/cm.svg | 15 + .../src/main/java/studio/flags/cn.svg | 11 + .../src/main/java/studio/flags/co.svg | 7 + .../src/main/java/studio/flags/cp.svg | 7 + .../src/main/java/studio/flags/cr.svg | 7 + .../src/main/java/studio/flags/cu.svg | 13 + .../src/main/java/studio/flags/cv.svg | 13 + .../src/main/java/studio/flags/cw.svg | 14 + .../src/main/java/studio/flags/cx.svg | 15 + .../src/main/java/studio/flags/cy.svg | 6 + .../src/main/java/studio/flags/cz.svg | 5 + .../src/main/java/studio/flags/de.svg | 5 + .../src/main/java/studio/flags/dg.svg | 130 ++++ .../src/main/java/studio/flags/dj.svg | 13 + .../src/main/java/studio/flags/dk.svg | 5 + .../src/main/java/studio/flags/dm.svg | 152 ++++ .../src/main/java/studio/flags/do.svg | 123 ++++ .../src/main/java/studio/flags/dz.svg | 5 + .../src/main/java/studio/flags/eac.svg | 48 ++ .../src/main/java/studio/flags/ec.svg | 138 ++++ .../src/main/java/studio/flags/ee.svg | 5 + .../src/main/java/studio/flags/eg.svg | 38 + .../src/main/java/studio/flags/eh.svg | 11 + .../src/main/java/studio/flags/er.svg | 13 + .../src/main/java/studio/flags/es-ct.svg | 4 + .../src/main/java/studio/flags/es-ga.svg | 187 +++++ .../src/main/java/studio/flags/es-pv.svg | 5 + .../src/main/java/studio/flags/es.svg | 547 ++++++++++++++ .../src/main/java/studio/flags/et.svg | 14 + .../src/main/java/studio/flags/eu.svg | 28 + .../src/main/java/studio/flags/fi.svg | 5 + .../src/main/java/studio/flags/fj.svg | 123 ++++ .../src/main/java/studio/flags/fk.svg | 89 +++ .../src/main/java/studio/flags/fm.svg | 11 + .../src/main/java/studio/flags/fo.svg | 12 + .../src/main/java/studio/flags/fr.svg | 5 + .../src/main/java/studio/flags/ga.svg | 7 + .../src/main/java/studio/flags/gb-eng.svg | 5 + .../src/main/java/studio/flags/gb-nir.svg | 131 ++++ .../src/main/java/studio/flags/gb-sct.svg | 4 + .../src/main/java/studio/flags/gb-wls.svg | 9 + .../src/main/java/studio/flags/gb.svg | 7 + .../src/main/java/studio/flags/gd.svg | 27 + .../src/main/java/studio/flags/ge.svg | 6 + .../src/main/java/studio/flags/gf.svg | 5 + .../src/main/java/studio/flags/gg.svg | 9 + .../src/main/java/studio/flags/gh.svg | 6 + .../src/main/java/studio/flags/gi.svg | 32 + .../src/main/java/studio/flags/gl.svg | 4 + .../src/main/java/studio/flags/gm.svg | 9 + .../src/main/java/studio/flags/gn.svg | 7 + .../src/main/java/studio/flags/gp.svg | 5 + .../src/main/java/studio/flags/gq.svg | 23 + .../src/main/java/studio/flags/gr.svg | 16 + .../src/main/java/studio/flags/gs.svg | 132 ++++ .../src/main/java/studio/flags/gt.svg | 204 ++++++ .../src/main/java/studio/flags/gu.svg | 23 + .../src/main/java/studio/flags/gw.svg | 15 + .../src/main/java/studio/flags/gy.svg | 9 + .../src/main/java/studio/flags/hk.svg | 8 + .../src/main/java/studio/flags/hm.svg | 8 + .../src/main/java/studio/flags/hn.svg | 18 + .../src/main/java/studio/flags/hr.svg | 56 ++ .../src/main/java/studio/flags/ht.svg | 116 +++ .../src/main/java/studio/flags/hu.svg | 7 + .../src/main/java/studio/flags/ic.svg | 7 + .../src/main/java/studio/flags/id.svg | 4 + .../src/main/java/studio/flags/ie.svg | 7 + .../src/main/java/studio/flags/il.svg | 14 + .../src/main/java/studio/flags/im.svg | 36 + .../src/main/java/studio/flags/in.svg | 25 + .../src/main/java/studio/flags/io.svg | 130 ++++ .../src/main/java/studio/flags/iq.svg | 10 + .../src/main/java/studio/flags/ir.svg | 219 ++++++ .../src/main/java/studio/flags/is.svg | 12 + .../src/main/java/studio/flags/it.svg | 7 + .../src/main/java/studio/flags/je.svg | 62 ++ .../src/main/java/studio/flags/jm.svg | 8 + .../src/main/java/studio/flags/jo.svg | 16 + .../src/main/java/studio/flags/jp.svg | 11 + .../src/main/java/studio/flags/ke.svg | 23 + .../src/main/java/studio/flags/kg.svg | 15 + .../src/main/java/studio/flags/kh.svg | 61 ++ .../src/main/java/studio/flags/ki.svg | 36 + .../src/main/java/studio/flags/km.svg | 16 + .../src/main/java/studio/flags/kn.svg | 14 + .../src/main/java/studio/flags/kp.svg | 15 + .../src/main/java/studio/flags/kr.svg | 17 + .../src/main/java/studio/flags/kw.svg | 13 + .../src/main/java/studio/flags/ky.svg | 103 +++ .../src/main/java/studio/flags/kz.svg | 36 + .../src/main/java/studio/flags/la.svg | 12 + .../src/main/java/studio/flags/lb.svg | 15 + .../src/main/java/studio/flags/lc.svg | 8 + .../src/main/java/studio/flags/li.svg | 43 ++ .../src/main/java/studio/flags/lk.svg | 22 + .../src/main/java/studio/flags/lr.svg | 14 + .../src/main/java/studio/flags/ls.svg | 8 + .../src/main/java/studio/flags/lt.svg | 7 + .../src/main/java/studio/flags/lu.svg | 5 + .../src/main/java/studio/flags/lv.svg | 6 + .../src/main/java/studio/flags/ly.svg | 13 + .../src/main/java/studio/flags/ma.svg | 4 + .../src/main/java/studio/flags/mc.svg | 6 + .../src/main/java/studio/flags/md.svg | 71 ++ .../src/main/java/studio/flags/me.svg | 118 +++ .../src/main/java/studio/flags/mf.svg | 5 + .../src/main/java/studio/flags/mg.svg | 7 + .../src/main/java/studio/flags/mh.svg | 8 + .../src/main/java/studio/flags/mk.svg | 5 + .../src/main/java/studio/flags/ml.svg | 7 + .../src/main/java/studio/flags/mm.svg | 10 + .../src/main/java/studio/flags/mn.svg | 14 + .../src/main/java/studio/flags/mo.svg | 9 + .../src/main/java/studio/flags/mp.svg | 86 +++ .../src/main/java/studio/flags/mq.svg | 5 + .../src/main/java/studio/flags/mr.svg | 6 + .../src/main/java/studio/flags/ms.svg | 25 + .../src/main/java/studio/flags/mt.svg | 56 ++ .../src/main/java/studio/flags/mu.svg | 8 + .../src/main/java/studio/flags/mv.svg | 6 + .../src/main/java/studio/flags/mw.svg | 15 + .../src/main/java/studio/flags/mx.svg | 377 ++++++++++ .../src/main/java/studio/flags/my.svg | 18 + .../src/main/java/studio/flags/mz.svg | 21 + .../src/main/java/studio/flags/na.svg | 16 + .../src/main/java/studio/flags/nc.svg | 12 + .../src/main/java/studio/flags/ne.svg | 6 + .../src/main/java/studio/flags/nf.svg | 11 + .../src/main/java/studio/flags/ng.svg | 6 + .../src/main/java/studio/flags/ni.svg | 129 ++++ .../src/main/java/studio/flags/nl.svg | 5 + .../src/main/java/studio/flags/no.svg | 7 + .../src/main/java/studio/flags/np.svg | 18 + .../src/main/java/studio/flags/nr.svg | 12 + .../src/main/java/studio/flags/nu.svg | 10 + .../src/main/java/studio/flags/nz.svg | 36 + .../src/main/java/studio/flags/om.svg | 115 +++ .../src/main/java/studio/flags/pa.svg | 13 + .../src/main/java/studio/flags/pc.svg | 33 + .../src/main/java/studio/flags/pe.svg | 4 + .../src/main/java/studio/flags/pf.svg | 18 + .../src/main/java/studio/flags/pg.svg | 16 + .../src/main/java/studio/flags/ph.svg | 6 + .../src/main/java/studio/flags/pk.svg | 15 + .../src/main/java/studio/flags/pl.svg | 6 + .../src/main/java/studio/flags/pm.svg | 5 + .../src/main/java/studio/flags/pn.svg | 53 ++ .../src/main/java/studio/flags/pr.svg | 13 + .../src/main/java/studio/flags/ps.svg | 15 + .../src/main/java/studio/flags/pt.svg | 57 ++ .../src/main/java/studio/flags/pw.svg | 11 + .../src/main/java/studio/flags/py.svg | 156 ++++ .../src/main/java/studio/flags/qa.svg | 4 + .../src/main/java/studio/flags/re.svg | 7 + .../src/main/java/studio/flags/ro.svg | 7 + .../src/main/java/studio/flags/rs.svg | 296 ++++++++ .../src/main/java/studio/flags/ru.svg | 5 + .../src/main/java/studio/flags/rw.svg | 13 + .../src/main/java/studio/flags/sa.svg | 25 + .../src/main/java/studio/flags/sb.svg | 13 + .../src/main/java/studio/flags/sc.svg | 7 + .../src/main/java/studio/flags/sd.svg | 13 + .../src/main/java/studio/flags/se.svg | 4 + .../src/main/java/studio/flags/sg.svg | 13 + .../src/main/java/studio/flags/sh-ac.svg | 690 ++++++++++++++++++ .../src/main/java/studio/flags/sh-hl.svg | 164 +++++ .../src/main/java/studio/flags/sh-ta.svg | 76 ++ .../src/main/java/studio/flags/sh.svg | 7 + .../src/main/java/studio/flags/si.svg | 18 + .../src/main/java/studio/flags/sj.svg | 7 + .../src/main/java/studio/flags/sk.svg | 9 + .../src/main/java/studio/flags/sl.svg | 12 + .../src/main/java/studio/flags/sm.svg | 73 ++ .../src/main/java/studio/flags/sn.svg | 8 + .../src/main/java/studio/flags/so.svg | 11 + .../src/main/java/studio/flags/sr.svg | 6 + .../src/main/java/studio/flags/ss.svg | 8 + .../src/main/java/studio/flags/st.svg | 16 + .../src/main/java/studio/flags/sv.svg | 594 +++++++++++++++ .../src/main/java/studio/flags/sx.svg | 56 ++ .../src/main/java/studio/flags/sy.svg | 6 + .../src/main/java/studio/flags/sz.svg | 34 + .../src/main/java/studio/flags/tc.svg | 50 ++ .../src/main/java/studio/flags/td.svg | 7 + .../src/main/java/studio/flags/tf.svg | 15 + .../src/main/java/studio/flags/tg.svg | 14 + .../src/main/java/studio/flags/th.svg | 7 + .../src/main/java/studio/flags/tj.svg | 26 + .../src/main/java/studio/flags/tk.svg | 5 + .../src/main/java/studio/flags/tl.svg | 13 + .../src/main/java/studio/flags/tm.svg | 205 ++++++ .../src/main/java/studio/flags/tn.svg | 4 + .../src/main/java/studio/flags/to.svg | 10 + .../src/main/java/studio/flags/tr.svg | 8 + .../src/main/java/studio/flags/tt.svg | 7 + .../src/main/java/studio/flags/tv.svg | 9 + .../src/main/java/studio/flags/tw.svg | 32 + .../src/main/java/studio/flags/tz.svg | 15 + .../src/main/java/studio/flags/ua.svg | 6 + .../src/main/java/studio/flags/ug.svg | 30 + .../src/main/java/studio/flags/um.svg | 9 + .../src/main/java/studio/flags/un.svg | 16 + .../src/main/java/studio/flags/us.svg | 9 + .../src/main/java/studio/flags/uy.svg | 28 + .../src/main/java/studio/flags/uz.svg | 30 + .../src/main/java/studio/flags/va.svg | 190 +++++ .../src/main/java/studio/flags/vc.svg | 8 + .../src/main/java/studio/flags/ve.svg | 26 + .../src/main/java/studio/flags/vg.svg | 59 ++ .../src/main/java/studio/flags/vi.svg | 28 + .../src/main/java/studio/flags/vn.svg | 11 + .../src/main/java/studio/flags/vu.svg | 21 + .../src/main/java/studio/flags/wf.svg | 5 + .../src/main/java/studio/flags/ws.svg | 7 + .../src/main/java/studio/flags/xk.svg | 5 + .../src/main/java/studio/flags/xx.svg | 4 + .../src/main/java/studio/flags/ye.svg | 7 + .../src/main/java/studio/flags/yt.svg | 5 + .../src/main/java/studio/flags/za.svg | 17 + .../src/main/java/studio/flags/zm.svg | 27 + .../src/main/java/studio/flags/zw.svg | 21 + 271 files changed, 10885 insertions(+) create mode 100644 studio-desktop/src/main/java/studio/LanguagesCellRenderer.java create mode 100644 studio-desktop/src/main/java/studio/flags/ad.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ae.svg create mode 100644 studio-desktop/src/main/java/studio/flags/af.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ag.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ai.svg create mode 100644 studio-desktop/src/main/java/studio/flags/al.svg create mode 100644 studio-desktop/src/main/java/studio/flags/am.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ao.svg create mode 100644 studio-desktop/src/main/java/studio/flags/aq.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ar.svg create mode 100644 studio-desktop/src/main/java/studio/flags/arab.svg create mode 100644 studio-desktop/src/main/java/studio/flags/as.svg create mode 100644 studio-desktop/src/main/java/studio/flags/at.svg create mode 100644 studio-desktop/src/main/java/studio/flags/au.svg create mode 100644 studio-desktop/src/main/java/studio/flags/aw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ax.svg create mode 100644 studio-desktop/src/main/java/studio/flags/az.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ba.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bb.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bd.svg create mode 100644 studio-desktop/src/main/java/studio/flags/be.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bh.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bi.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bj.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bo.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bq.svg create mode 100644 studio-desktop/src/main/java/studio/flags/br.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bs.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/by.svg create mode 100644 studio-desktop/src/main/java/studio/flags/bz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ca.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cd.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cefta.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ch.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ci.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ck.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/co.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cp.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cx.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cy.svg create mode 100644 studio-desktop/src/main/java/studio/flags/cz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/de.svg create mode 100644 studio-desktop/src/main/java/studio/flags/dg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/dj.svg create mode 100644 studio-desktop/src/main/java/studio/flags/dk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/dm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/do.svg create mode 100644 studio-desktop/src/main/java/studio/flags/dz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/eac.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ec.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ee.svg create mode 100644 studio-desktop/src/main/java/studio/flags/eg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/eh.svg create mode 100644 studio-desktop/src/main/java/studio/flags/er.svg create mode 100644 studio-desktop/src/main/java/studio/flags/es-ct.svg create mode 100644 studio-desktop/src/main/java/studio/flags/es-ga.svg create mode 100644 studio-desktop/src/main/java/studio/flags/es-pv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/es.svg create mode 100644 studio-desktop/src/main/java/studio/flags/et.svg create mode 100644 studio-desktop/src/main/java/studio/flags/eu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/fi.svg create mode 100644 studio-desktop/src/main/java/studio/flags/fj.svg create mode 100644 studio-desktop/src/main/java/studio/flags/fk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/fm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/fo.svg create mode 100644 studio-desktop/src/main/java/studio/flags/fr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ga.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gb-eng.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gb-nir.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gb-sct.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gb-wls.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gb.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gd.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ge.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gh.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gi.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gp.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gq.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gs.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/gy.svg create mode 100644 studio-desktop/src/main/java/studio/flags/hk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/hm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/hn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/hr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ht.svg create mode 100644 studio-desktop/src/main/java/studio/flags/hu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ic.svg create mode 100644 studio-desktop/src/main/java/studio/flags/id.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ie.svg create mode 100644 studio-desktop/src/main/java/studio/flags/il.svg create mode 100644 studio-desktop/src/main/java/studio/flags/im.svg create mode 100644 studio-desktop/src/main/java/studio/flags/in.svg create mode 100644 studio-desktop/src/main/java/studio/flags/io.svg create mode 100644 studio-desktop/src/main/java/studio/flags/iq.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ir.svg create mode 100644 studio-desktop/src/main/java/studio/flags/is.svg create mode 100644 studio-desktop/src/main/java/studio/flags/it.svg create mode 100644 studio-desktop/src/main/java/studio/flags/je.svg create mode 100644 studio-desktop/src/main/java/studio/flags/jm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/jo.svg create mode 100644 studio-desktop/src/main/java/studio/flags/jp.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ke.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kh.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ki.svg create mode 100644 studio-desktop/src/main/java/studio/flags/km.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kp.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ky.svg create mode 100644 studio-desktop/src/main/java/studio/flags/kz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/la.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lb.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/li.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ls.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/lv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ly.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ma.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/md.svg create mode 100644 studio-desktop/src/main/java/studio/flags/me.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mh.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ml.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mo.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mp.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mq.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ms.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mx.svg create mode 100644 studio-desktop/src/main/java/studio/flags/my.svg create mode 100644 studio-desktop/src/main/java/studio/flags/mz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/na.svg create mode 100644 studio-desktop/src/main/java/studio/flags/nc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ne.svg create mode 100644 studio-desktop/src/main/java/studio/flags/nf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ng.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ni.svg create mode 100644 studio-desktop/src/main/java/studio/flags/nl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/no.svg create mode 100644 studio-desktop/src/main/java/studio/flags/np.svg create mode 100644 studio-desktop/src/main/java/studio/flags/nr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/nu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/nz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/om.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pa.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pe.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ph.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ps.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/pw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/py.svg create mode 100644 studio-desktop/src/main/java/studio/flags/qa.svg create mode 100644 studio-desktop/src/main/java/studio/flags/re.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ro.svg create mode 100644 studio-desktop/src/main/java/studio/flags/rs.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ru.svg create mode 100644 studio-desktop/src/main/java/studio/flags/rw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sa.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sb.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sd.svg create mode 100644 studio-desktop/src/main/java/studio/flags/se.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sh-ac.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sh-hl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sh-ta.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sh.svg create mode 100644 studio-desktop/src/main/java/studio/flags/si.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sj.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/so.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ss.svg create mode 100644 studio-desktop/src/main/java/studio/flags/st.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sx.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sy.svg create mode 100644 studio-desktop/src/main/java/studio/flags/sz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/td.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/th.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tj.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tl.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/to.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tr.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tv.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tw.svg create mode 100644 studio-desktop/src/main/java/studio/flags/tz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ua.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ug.svg create mode 100644 studio-desktop/src/main/java/studio/flags/um.svg create mode 100644 studio-desktop/src/main/java/studio/flags/un.svg create mode 100644 studio-desktop/src/main/java/studio/flags/us.svg create mode 100644 studio-desktop/src/main/java/studio/flags/uy.svg create mode 100644 studio-desktop/src/main/java/studio/flags/uz.svg create mode 100644 studio-desktop/src/main/java/studio/flags/va.svg create mode 100644 studio-desktop/src/main/java/studio/flags/vc.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ve.svg create mode 100644 studio-desktop/src/main/java/studio/flags/vg.svg create mode 100644 studio-desktop/src/main/java/studio/flags/vi.svg create mode 100644 studio-desktop/src/main/java/studio/flags/vn.svg create mode 100644 studio-desktop/src/main/java/studio/flags/vu.svg create mode 100644 studio-desktop/src/main/java/studio/flags/wf.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ws.svg create mode 100644 studio-desktop/src/main/java/studio/flags/xk.svg create mode 100644 studio-desktop/src/main/java/studio/flags/xx.svg create mode 100644 studio-desktop/src/main/java/studio/flags/ye.svg create mode 100644 studio-desktop/src/main/java/studio/flags/yt.svg create mode 100644 studio-desktop/src/main/java/studio/flags/za.svg create mode 100644 studio-desktop/src/main/java/studio/flags/zm.svg create mode 100644 studio-desktop/src/main/java/studio/flags/zw.svg diff --git a/studio-desktop/src/main/java/studio/LanguagesCellRenderer.java b/studio-desktop/src/main/java/studio/LanguagesCellRenderer.java new file mode 100644 index 000000000..e2d8a2f55 --- /dev/null +++ b/studio-desktop/src/main/java/studio/LanguagesCellRenderer.java @@ -0,0 +1,109 @@ +package studio; + +import static org.apache.batik.transcoder.SVGAbstractTranscoder.KEY_WIDTH; +import static org.apache.batik.transcoder.XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT; +import static org.apache.batik.transcoder.XMLAbstractTranscoder.KEY_DOCUMENT_ELEMENT_NAMESPACE_URI; +import static org.apache.batik.transcoder.XMLAbstractTranscoder.KEY_DOM_IMPLEMENTATION; +import static org.apache.batik.util.SVGConstants.SVG_NAMESPACE_URI; +import static org.apache.batik.util.SVGConstants.SVG_SVG_TAG; + +import java.awt.Component; +import java.awt.Dimension; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.ImageIcon; +import javax.swing.JList; + +import org.apache.batik.anim.dom.SVGDOMImplementation; +import org.apache.batik.transcoder.TranscoderException; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; +import org.apache.batik.transcoder.TranscodingHints; +import org.apache.batik.transcoder.image.ImageTranscoder; + +public class LanguagesCellRenderer extends DefaultListCellRenderer { + + private static Map mappings = new HashMap(); + + /** + * Reads in an SVG image file and return it as a BufferedImage with the given width and a height + * where the original aspect ratio is preserved. + * + * @param url URL referencing the SVG image file, which is typically an XML file + * @param width width in pixels the returned BufferedImage should be + * + * @return a valid image representing the SVG file + * @throws IOException if the file cannot be parsed as valid SVG + */ + public static BufferedImage loadSvg(URL url, float width) throws IOException { + SvgTranscoder transcoder = new SvgTranscoder(); + transcoder.setTranscodingHints(getHints(width)); + try { + TranscoderInput input = new TranscoderInput(url.openStream()); + transcoder.transcode(input, null); + } catch (TranscoderException e) { + throw new IOException("Error parsing SVG file " + url, e); + } + BufferedImage image = transcoder.getImage(); + return image; + } + + private static TranscodingHints getHints(float width) { + TranscodingHints hints = new TranscodingHints(); + hints.put(KEY_DOM_IMPLEMENTATION, SVGDOMImplementation.getDOMImplementation()); + hints.put(KEY_DOCUMENT_ELEMENT_NAMESPACE_URI, SVG_NAMESPACE_URI); + hints.put(KEY_DOCUMENT_ELEMENT, SVG_SVG_TAG); + hints.put(KEY_WIDTH, width); + return hints; + } + + private static class SvgTranscoder extends ImageTranscoder { + + private BufferedImage image = null; + + @Override + public BufferedImage createImage(int width, int height) { + image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + return image; + } + + @Override + public void writeImage(BufferedImage img, TranscoderOutput out) {} + + BufferedImage getImage() { + return image; + } + } + + + @Override + public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, + boolean cellHasFocus) { + + if ( value == null ) { + return super.getListCellRendererComponent(list, "-", index, isSelected, cellHasFocus); + } + ImageIcon icon = mappings.get(value.toString()); + if ( icon == null ) { + URL url = getClass().getResource("/studio/flags/" + value.toString().split("_")[1].toLowerCase() + ".svg"); + try { + icon = new ImageIcon(loadSvg(url, 24)); + } catch (IOException e) { + e.printStackTrace(); + } + mappings.put(value.toString(), icon); + } + + super.getListCellRendererComponent(list, icon, index, isSelected, cellHasFocus); + this.setPreferredSize(new Dimension(32, 32)); + return this; + + //return res; + } + +} diff --git a/studio-desktop/src/main/java/studio/flags/ad.svg b/studio-desktop/src/main/java/studio/flags/ad.svg new file mode 100644 index 000000000..4bd91b72b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ad.svg @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ae.svg b/studio-desktop/src/main/java/studio/flags/ae.svg new file mode 100644 index 000000000..b59e11352 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ae.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/af.svg b/studio-desktop/src/main/java/studio/flags/af.svg new file mode 100644 index 000000000..0b7939c69 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/af.svg @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ag.svg b/studio-desktop/src/main/java/studio/flags/ag.svg new file mode 100644 index 000000000..9b951b6a5 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ag.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ai.svg b/studio-desktop/src/main/java/studio/flags/ai.svg new file mode 100644 index 000000000..eeaebcf64 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ai.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/al.svg b/studio-desktop/src/main/java/studio/flags/al.svg new file mode 100644 index 000000000..15ee8bbe2 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/al.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/am.svg b/studio-desktop/src/main/java/studio/flags/am.svg new file mode 100644 index 000000000..a188adfe4 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/am.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ao.svg b/studio-desktop/src/main/java/studio/flags/ao.svg new file mode 100644 index 000000000..46d6600ad --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ao.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/aq.svg b/studio-desktop/src/main/java/studio/flags/aq.svg new file mode 100644 index 000000000..a4d9a201f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/aq.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ar.svg b/studio-desktop/src/main/java/studio/flags/ar.svg new file mode 100644 index 000000000..984d6ea6a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ar.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/arab.svg b/studio-desktop/src/main/java/studio/flags/arab.svg new file mode 100644 index 000000000..841f11adf --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/arab.svg @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/as.svg b/studio-desktop/src/main/java/studio/flags/as.svg new file mode 100644 index 000000000..b0789e9c9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/as.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/at.svg b/studio-desktop/src/main/java/studio/flags/at.svg new file mode 100644 index 000000000..758ced641 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/at.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/au.svg b/studio-desktop/src/main/java/studio/flags/au.svg new file mode 100644 index 000000000..38bb24505 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/au.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/aw.svg b/studio-desktop/src/main/java/studio/flags/aw.svg new file mode 100644 index 000000000..1f03d61a2 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/aw.svg @@ -0,0 +1,186 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ax.svg b/studio-desktop/src/main/java/studio/flags/ax.svg new file mode 100644 index 000000000..481d2a33c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ax.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/az.svg b/studio-desktop/src/main/java/studio/flags/az.svg new file mode 100644 index 000000000..d692e2250 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/az.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ba.svg b/studio-desktop/src/main/java/studio/flags/ba.svg new file mode 100644 index 000000000..456ca1236 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ba.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bb.svg b/studio-desktop/src/main/java/studio/flags/bb.svg new file mode 100644 index 000000000..5af2bd030 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bb.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bd.svg b/studio-desktop/src/main/java/studio/flags/bd.svg new file mode 100644 index 000000000..86fcfbab0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bd.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/be.svg b/studio-desktop/src/main/java/studio/flags/be.svg new file mode 100644 index 000000000..31d6210c7 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/be.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bf.svg b/studio-desktop/src/main/java/studio/flags/bf.svg new file mode 100644 index 000000000..a5078df3f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bf.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bg.svg b/studio-desktop/src/main/java/studio/flags/bg.svg new file mode 100644 index 000000000..78412c5d2 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bg.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bh.svg b/studio-desktop/src/main/java/studio/flags/bh.svg new file mode 100644 index 000000000..2d131aa59 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bh.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bi.svg b/studio-desktop/src/main/java/studio/flags/bi.svg new file mode 100644 index 000000000..36a0d3a68 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bi.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bj.svg b/studio-desktop/src/main/java/studio/flags/bj.svg new file mode 100644 index 000000000..bb27414c0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bj.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bl.svg b/studio-desktop/src/main/java/studio/flags/bl.svg new file mode 100644 index 000000000..65550d936 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bl.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bm.svg b/studio-desktop/src/main/java/studio/flags/bm.svg new file mode 100644 index 000000000..b4df19244 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bm.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bn.svg b/studio-desktop/src/main/java/studio/flags/bn.svg new file mode 100644 index 000000000..b536651cf --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bn.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bo.svg b/studio-desktop/src/main/java/studio/flags/bo.svg new file mode 100644 index 000000000..b69b23089 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bo.svg @@ -0,0 +1,674 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bq.svg b/studio-desktop/src/main/java/studio/flags/bq.svg new file mode 100644 index 000000000..4b9168e13 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bq.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/br.svg b/studio-desktop/src/main/java/studio/flags/br.svg new file mode 100644 index 000000000..be62f6ff9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/br.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bs.svg b/studio-desktop/src/main/java/studio/flags/bs.svg new file mode 100644 index 000000000..0faa4bbac --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bs.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bt.svg b/studio-desktop/src/main/java/studio/flags/bt.svg new file mode 100644 index 000000000..81f6788c0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bt.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bv.svg b/studio-desktop/src/main/java/studio/flags/bv.svg new file mode 100644 index 000000000..dcc6ad106 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bv.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bw.svg b/studio-desktop/src/main/java/studio/flags/bw.svg new file mode 100644 index 000000000..328e13c11 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bw.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/by.svg b/studio-desktop/src/main/java/studio/flags/by.svg new file mode 100644 index 000000000..ab7984dc9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/by.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/bz.svg b/studio-desktop/src/main/java/studio/flags/bz.svg new file mode 100644 index 000000000..e99106a56 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/bz.svg @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ca.svg b/studio-desktop/src/main/java/studio/flags/ca.svg new file mode 100644 index 000000000..84cde348e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ca.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cc.svg b/studio-desktop/src/main/java/studio/flags/cc.svg new file mode 100644 index 000000000..f6c1755ce --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cc.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cd.svg b/studio-desktop/src/main/java/studio/flags/cd.svg new file mode 100644 index 000000000..ea1772873 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cd.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cefta.svg b/studio-desktop/src/main/java/studio/flags/cefta.svg new file mode 100644 index 000000000..ff1a19bb6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cefta.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cf.svg b/studio-desktop/src/main/java/studio/flags/cf.svg new file mode 100644 index 000000000..b0625db75 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cf.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cg.svg b/studio-desktop/src/main/java/studio/flags/cg.svg new file mode 100644 index 000000000..f7868842f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cg.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ch.svg b/studio-desktop/src/main/java/studio/flags/ch.svg new file mode 100644 index 000000000..52578bfde --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ch.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ci.svg b/studio-desktop/src/main/java/studio/flags/ci.svg new file mode 100644 index 000000000..2abf64119 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ci.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ck.svg b/studio-desktop/src/main/java/studio/flags/ck.svg new file mode 100644 index 000000000..43a105763 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ck.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cl.svg b/studio-desktop/src/main/java/studio/flags/cl.svg new file mode 100644 index 000000000..5fb6096b7 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cl.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cm.svg b/studio-desktop/src/main/java/studio/flags/cm.svg new file mode 100644 index 000000000..ed4952b43 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cm.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cn.svg b/studio-desktop/src/main/java/studio/flags/cn.svg new file mode 100644 index 000000000..e152f0166 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cn.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/co.svg b/studio-desktop/src/main/java/studio/flags/co.svg new file mode 100644 index 000000000..5804bfe48 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/co.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cp.svg b/studio-desktop/src/main/java/studio/flags/cp.svg new file mode 100644 index 000000000..ea3bfdcb4 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cp.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cr.svg b/studio-desktop/src/main/java/studio/flags/cr.svg new file mode 100644 index 000000000..4e7889e22 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cr.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cu.svg b/studio-desktop/src/main/java/studio/flags/cu.svg new file mode 100644 index 000000000..a28490235 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cu.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cv.svg b/studio-desktop/src/main/java/studio/flags/cv.svg new file mode 100644 index 000000000..1170cd767 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cv.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cw.svg b/studio-desktop/src/main/java/studio/flags/cw.svg new file mode 100644 index 000000000..57062abaa --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cw.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cx.svg b/studio-desktop/src/main/java/studio/flags/cx.svg new file mode 100644 index 000000000..f14536f03 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cx.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cy.svg b/studio-desktop/src/main/java/studio/flags/cy.svg new file mode 100644 index 000000000..39a87c870 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cy.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/cz.svg b/studio-desktop/src/main/java/studio/flags/cz.svg new file mode 100644 index 000000000..dcd0a6b1e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/cz.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/de.svg b/studio-desktop/src/main/java/studio/flags/de.svg new file mode 100644 index 000000000..05a0a69ae --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/de.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/dg.svg b/studio-desktop/src/main/java/studio/flags/dg.svg new file mode 100644 index 000000000..0b8baf149 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/dg.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/dj.svg b/studio-desktop/src/main/java/studio/flags/dj.svg new file mode 100644 index 000000000..f5534d2a0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/dj.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/dk.svg b/studio-desktop/src/main/java/studio/flags/dk.svg new file mode 100644 index 000000000..5aaaa1906 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/dk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/dm.svg b/studio-desktop/src/main/java/studio/flags/dm.svg new file mode 100644 index 000000000..6f8f36646 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/dm.svg @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/do.svg b/studio-desktop/src/main/java/studio/flags/do.svg new file mode 100644 index 000000000..867e12d1a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/do.svg @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/dz.svg b/studio-desktop/src/main/java/studio/flags/dz.svg new file mode 100644 index 000000000..8abcd258e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/dz.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/eac.svg b/studio-desktop/src/main/java/studio/flags/eac.svg new file mode 100644 index 000000000..385fe9d66 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/eac.svg @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ec.svg b/studio-desktop/src/main/java/studio/flags/ec.svg new file mode 100644 index 000000000..9545c5ddd --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ec.svg @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ee.svg b/studio-desktop/src/main/java/studio/flags/ee.svg new file mode 100644 index 000000000..5a6a7e37e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ee.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/eg.svg b/studio-desktop/src/main/java/studio/flags/eg.svg new file mode 100644 index 000000000..3ef77112c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/eg.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/eh.svg b/studio-desktop/src/main/java/studio/flags/eh.svg new file mode 100644 index 000000000..ae509fa8b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/eh.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/er.svg b/studio-desktop/src/main/java/studio/flags/er.svg new file mode 100644 index 000000000..0f140e092 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/er.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/es-ct.svg b/studio-desktop/src/main/java/studio/flags/es-ct.svg new file mode 100644 index 000000000..a06a2e3d3 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/es-ct.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/es-ga.svg b/studio-desktop/src/main/java/studio/flags/es-ga.svg new file mode 100644 index 000000000..2fecfa090 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/es-ga.svg @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/es-pv.svg b/studio-desktop/src/main/java/studio/flags/es-pv.svg new file mode 100644 index 000000000..7d383ed5e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/es-pv.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/es.svg b/studio-desktop/src/main/java/studio/flags/es.svg new file mode 100644 index 000000000..0e6338fac --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/es.svg @@ -0,0 +1,547 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/et.svg b/studio-desktop/src/main/java/studio/flags/et.svg new file mode 100644 index 000000000..eb7f3c423 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/et.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/eu.svg b/studio-desktop/src/main/java/studio/flags/eu.svg new file mode 100644 index 000000000..4a07fbe58 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/eu.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/fi.svg b/studio-desktop/src/main/java/studio/flags/fi.svg new file mode 100644 index 000000000..aba2ef3b0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/fi.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/fj.svg b/studio-desktop/src/main/java/studio/flags/fj.svg new file mode 100644 index 000000000..7a1cade2d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/fj.svg @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/fk.svg b/studio-desktop/src/main/java/studio/flags/fk.svg new file mode 100644 index 000000000..21e654f22 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/fk.svg @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/fm.svg b/studio-desktop/src/main/java/studio/flags/fm.svg new file mode 100644 index 000000000..4f7d31324 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/fm.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/fo.svg b/studio-desktop/src/main/java/studio/flags/fo.svg new file mode 100644 index 000000000..eec994583 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/fo.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/fr.svg b/studio-desktop/src/main/java/studio/flags/fr.svg new file mode 100644 index 000000000..0f60170fc --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/fr.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ga.svg b/studio-desktop/src/main/java/studio/flags/ga.svg new file mode 100644 index 000000000..113a5b58a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ga.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gb-eng.svg b/studio-desktop/src/main/java/studio/flags/gb-eng.svg new file mode 100644 index 000000000..ee48fed99 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gb-eng.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gb-nir.svg b/studio-desktop/src/main/java/studio/flags/gb-nir.svg new file mode 100644 index 000000000..77a91f071 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gb-nir.svg @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gb-sct.svg b/studio-desktop/src/main/java/studio/flags/gb-sct.svg new file mode 100644 index 000000000..44d38cc10 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gb-sct.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gb-wls.svg b/studio-desktop/src/main/java/studio/flags/gb-wls.svg new file mode 100644 index 000000000..31268824c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gb-wls.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gb.svg b/studio-desktop/src/main/java/studio/flags/gb.svg new file mode 100644 index 000000000..ce4d1e000 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gb.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gd.svg b/studio-desktop/src/main/java/studio/flags/gd.svg new file mode 100644 index 000000000..c3b2cef56 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gd.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ge.svg b/studio-desktop/src/main/java/studio/flags/ge.svg new file mode 100644 index 000000000..53b709fc1 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ge.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gf.svg b/studio-desktop/src/main/java/studio/flags/gf.svg new file mode 100644 index 000000000..9cf5aa2b1 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gg.svg b/studio-desktop/src/main/java/studio/flags/gg.svg new file mode 100644 index 000000000..480f5503f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gg.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gh.svg b/studio-desktop/src/main/java/studio/flags/gh.svg new file mode 100644 index 000000000..a64271b84 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gh.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gi.svg b/studio-desktop/src/main/java/studio/flags/gi.svg new file mode 100644 index 000000000..7b26bb2e9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gi.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gl.svg b/studio-desktop/src/main/java/studio/flags/gl.svg new file mode 100644 index 000000000..eaa817b1a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gl.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gm.svg b/studio-desktop/src/main/java/studio/flags/gm.svg new file mode 100644 index 000000000..2a8f72443 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gm.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gn.svg b/studio-desktop/src/main/java/studio/flags/gn.svg new file mode 100644 index 000000000..ae81f9d7b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gn.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gp.svg b/studio-desktop/src/main/java/studio/flags/gp.svg new file mode 100644 index 000000000..9dd8e3bba --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gp.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gq.svg b/studio-desktop/src/main/java/studio/flags/gq.svg new file mode 100644 index 000000000..5fd7b6a17 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gq.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gr.svg b/studio-desktop/src/main/java/studio/flags/gr.svg new file mode 100644 index 000000000..a2688303a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gr.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gs.svg b/studio-desktop/src/main/java/studio/flags/gs.svg new file mode 100644 index 000000000..1db72cffb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gs.svg @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gt.svg b/studio-desktop/src/main/java/studio/flags/gt.svg new file mode 100644 index 000000000..97ea6aa5b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gt.svg @@ -0,0 +1,204 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gu.svg b/studio-desktop/src/main/java/studio/flags/gu.svg new file mode 100644 index 000000000..57024874f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gu.svg @@ -0,0 +1,23 @@ + + + + + + + + + + G + U + A + M + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gw.svg b/studio-desktop/src/main/java/studio/flags/gw.svg new file mode 100644 index 000000000..61a054812 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gw.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/gy.svg b/studio-desktop/src/main/java/studio/flags/gy.svg new file mode 100644 index 000000000..35e2f08bb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/gy.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/hk.svg b/studio-desktop/src/main/java/studio/flags/hk.svg new file mode 100644 index 000000000..eef02a18b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/hk.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/hm.svg b/studio-desktop/src/main/java/studio/flags/hm.svg new file mode 100644 index 000000000..1f4d00704 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/hm.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/hn.svg b/studio-desktop/src/main/java/studio/flags/hn.svg new file mode 100644 index 000000000..847df20c7 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/hn.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/hr.svg b/studio-desktop/src/main/java/studio/flags/hr.svg new file mode 100644 index 000000000..91009eb7d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/hr.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ht.svg b/studio-desktop/src/main/java/studio/flags/ht.svg new file mode 100644 index 000000000..a61736cda --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ht.svg @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/hu.svg b/studio-desktop/src/main/java/studio/flags/hu.svg new file mode 100644 index 000000000..088242d93 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/hu.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ic.svg b/studio-desktop/src/main/java/studio/flags/ic.svg new file mode 100644 index 000000000..096603d4b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/id.svg b/studio-desktop/src/main/java/studio/flags/id.svg new file mode 100644 index 000000000..df0801815 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/id.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ie.svg b/studio-desktop/src/main/java/studio/flags/ie.svg new file mode 100644 index 000000000..e13de22df --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ie.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/il.svg b/studio-desktop/src/main/java/studio/flags/il.svg new file mode 100644 index 000000000..0a2a6d99b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/il.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/im.svg b/studio-desktop/src/main/java/studio/flags/im.svg new file mode 100644 index 000000000..cff1c4b2b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/im.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/in.svg b/studio-desktop/src/main/java/studio/flags/in.svg new file mode 100644 index 000000000..26a02cff0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/in.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/io.svg b/studio-desktop/src/main/java/studio/flags/io.svg new file mode 100644 index 000000000..6f1a8ca20 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/io.svg @@ -0,0 +1,130 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/iq.svg b/studio-desktop/src/main/java/studio/flags/iq.svg new file mode 100644 index 000000000..a64456d4f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/iq.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ir.svg b/studio-desktop/src/main/java/studio/flags/ir.svg new file mode 100644 index 000000000..095d9717e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ir.svg @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/is.svg b/studio-desktop/src/main/java/studio/flags/is.svg new file mode 100644 index 000000000..26510b99e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/is.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/it.svg b/studio-desktop/src/main/java/studio/flags/it.svg new file mode 100644 index 000000000..b9596d050 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/it.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/je.svg b/studio-desktop/src/main/java/studio/flags/je.svg new file mode 100644 index 000000000..8a9fdd57e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/je.svg @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/jm.svg b/studio-desktop/src/main/java/studio/flags/jm.svg new file mode 100644 index 000000000..07f023c79 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/jm.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/jo.svg b/studio-desktop/src/main/java/studio/flags/jo.svg new file mode 100644 index 000000000..fbbd68104 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/jo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/jp.svg b/studio-desktop/src/main/java/studio/flags/jp.svg new file mode 100644 index 000000000..118686a0e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/jp.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ke.svg b/studio-desktop/src/main/java/studio/flags/ke.svg new file mode 100644 index 000000000..110600ec9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ke.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kg.svg b/studio-desktop/src/main/java/studio/flags/kg.svg new file mode 100644 index 000000000..2ab176a3b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kg.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kh.svg b/studio-desktop/src/main/java/studio/flags/kh.svg new file mode 100644 index 000000000..4b63b327d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kh.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ki.svg b/studio-desktop/src/main/java/studio/flags/ki.svg new file mode 100644 index 000000000..14dab1530 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ki.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/km.svg b/studio-desktop/src/main/java/studio/flags/km.svg new file mode 100644 index 000000000..d9b775119 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/km.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kn.svg b/studio-desktop/src/main/java/studio/flags/kn.svg new file mode 100644 index 000000000..42d5adfe5 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kn.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kp.svg b/studio-desktop/src/main/java/studio/flags/kp.svg new file mode 100644 index 000000000..253930406 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kp.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kr.svg b/studio-desktop/src/main/java/studio/flags/kr.svg new file mode 100644 index 000000000..af3d35eb5 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kr.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kw.svg b/studio-desktop/src/main/java/studio/flags/kw.svg new file mode 100644 index 000000000..b2fe54faa --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kw.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ky.svg b/studio-desktop/src/main/java/studio/flags/ky.svg new file mode 100644 index 000000000..e55d5207d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ky.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/kz.svg b/studio-desktop/src/main/java/studio/flags/kz.svg new file mode 100644 index 000000000..f9f9b98fe --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/kz.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/la.svg b/studio-desktop/src/main/java/studio/flags/la.svg new file mode 100644 index 000000000..af70d0dcc --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/la.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lb.svg b/studio-desktop/src/main/java/studio/flags/lb.svg new file mode 100644 index 000000000..65201091b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lb.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lc.svg b/studio-desktop/src/main/java/studio/flags/lc.svg new file mode 100644 index 000000000..aa18fac83 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lc.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/li.svg b/studio-desktop/src/main/java/studio/flags/li.svg new file mode 100644 index 000000000..bf8181029 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/li.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lk.svg b/studio-desktop/src/main/java/studio/flags/lk.svg new file mode 100644 index 000000000..08212a5b8 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lk.svg @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lr.svg b/studio-desktop/src/main/java/studio/flags/lr.svg new file mode 100644 index 000000000..74382abbe --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lr.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ls.svg b/studio-desktop/src/main/java/studio/flags/ls.svg new file mode 100644 index 000000000..605c087af --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ls.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lt.svg b/studio-desktop/src/main/java/studio/flags/lt.svg new file mode 100644 index 000000000..52ada948c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lt.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lu.svg b/studio-desktop/src/main/java/studio/flags/lu.svg new file mode 100644 index 000000000..037c31524 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lu.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/lv.svg b/studio-desktop/src/main/java/studio/flags/lv.svg new file mode 100644 index 000000000..5af883c70 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/lv.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ly.svg b/studio-desktop/src/main/java/studio/flags/ly.svg new file mode 100644 index 000000000..4375a9eaf --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ly.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ma.svg b/studio-desktop/src/main/java/studio/flags/ma.svg new file mode 100644 index 000000000..804166728 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ma.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mc.svg b/studio-desktop/src/main/java/studio/flags/mc.svg new file mode 100644 index 000000000..04173a415 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mc.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/md.svg b/studio-desktop/src/main/java/studio/flags/md.svg new file mode 100644 index 000000000..18a77ea92 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/md.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/me.svg b/studio-desktop/src/main/java/studio/flags/me.svg new file mode 100644 index 000000000..37e96b00a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/me.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mf.svg b/studio-desktop/src/main/java/studio/flags/mf.svg new file mode 100644 index 000000000..8d3285b86 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mg.svg b/studio-desktop/src/main/java/studio/flags/mg.svg new file mode 100644 index 000000000..4f901cad0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mg.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mh.svg b/studio-desktop/src/main/java/studio/flags/mh.svg new file mode 100644 index 000000000..1db268d22 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mh.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mk.svg b/studio-desktop/src/main/java/studio/flags/mk.svg new file mode 100644 index 000000000..0ee923a35 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ml.svg b/studio-desktop/src/main/java/studio/flags/ml.svg new file mode 100644 index 000000000..665d6b243 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ml.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mm.svg b/studio-desktop/src/main/java/studio/flags/mm.svg new file mode 100644 index 000000000..391f0c70b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mm.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mn.svg b/studio-desktop/src/main/java/studio/flags/mn.svg new file mode 100644 index 000000000..998fe5ceb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mn.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mo.svg b/studio-desktop/src/main/java/studio/flags/mo.svg new file mode 100644 index 000000000..bd5cbcd98 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mp.svg b/studio-desktop/src/main/java/studio/flags/mp.svg new file mode 100644 index 000000000..6179fb7d7 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mp.svg @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mq.svg b/studio-desktop/src/main/java/studio/flags/mq.svg new file mode 100644 index 000000000..dcf005443 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mq.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mr.svg b/studio-desktop/src/main/java/studio/flags/mr.svg new file mode 100644 index 000000000..ffe8c114f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mr.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ms.svg b/studio-desktop/src/main/java/studio/flags/ms.svg new file mode 100644 index 000000000..c06dfccf8 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ms.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mt.svg b/studio-desktop/src/main/java/studio/flags/mt.svg new file mode 100644 index 000000000..f53431568 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mt.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mu.svg b/studio-desktop/src/main/java/studio/flags/mu.svg new file mode 100644 index 000000000..2afe1d384 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mu.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mv.svg b/studio-desktop/src/main/java/studio/flags/mv.svg new file mode 100644 index 000000000..c9a6c5bcc --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mv.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mw.svg b/studio-desktop/src/main/java/studio/flags/mw.svg new file mode 100644 index 000000000..25bbf2efc --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mw.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mx.svg b/studio-desktop/src/main/java/studio/flags/mx.svg new file mode 100644 index 000000000..bb991c17f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mx.svg @@ -0,0 +1,377 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/my.svg b/studio-desktop/src/main/java/studio/flags/my.svg new file mode 100644 index 000000000..b10f76e61 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/my.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/mz.svg b/studio-desktop/src/main/java/studio/flags/mz.svg new file mode 100644 index 000000000..bb751482c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/mz.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/na.svg b/studio-desktop/src/main/java/studio/flags/na.svg new file mode 100644 index 000000000..36ac8d77e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/na.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/nc.svg b/studio-desktop/src/main/java/studio/flags/nc.svg new file mode 100644 index 000000000..1cc81eb01 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/nc.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ne.svg b/studio-desktop/src/main/java/studio/flags/ne.svg new file mode 100644 index 000000000..a96b027ab --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ne.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/nf.svg b/studio-desktop/src/main/java/studio/flags/nf.svg new file mode 100644 index 000000000..d9be1566c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/nf.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ng.svg b/studio-desktop/src/main/java/studio/flags/ng.svg new file mode 100644 index 000000000..62813e861 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ng.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ni.svg b/studio-desktop/src/main/java/studio/flags/ni.svg new file mode 100644 index 000000000..847f33125 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ni.svg @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/nl.svg b/studio-desktop/src/main/java/studio/flags/nl.svg new file mode 100644 index 000000000..49ca5bc00 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/nl.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/no.svg b/studio-desktop/src/main/java/studio/flags/no.svg new file mode 100644 index 000000000..939920d40 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/no.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/np.svg b/studio-desktop/src/main/java/studio/flags/np.svg new file mode 100644 index 000000000..498a1000f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/np.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/nr.svg b/studio-desktop/src/main/java/studio/flags/nr.svg new file mode 100644 index 000000000..c8c827e70 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/nr.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/nu.svg b/studio-desktop/src/main/java/studio/flags/nu.svg new file mode 100644 index 000000000..ce316723d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/nu.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/nz.svg b/studio-desktop/src/main/java/studio/flags/nz.svg new file mode 100644 index 000000000..ee617d6f2 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/nz.svg @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/om.svg b/studio-desktop/src/main/java/studio/flags/om.svg new file mode 100644 index 000000000..2021f9386 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/om.svg @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pa.svg b/studio-desktop/src/main/java/studio/flags/pa.svg new file mode 100644 index 000000000..108c40bff --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pa.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pc.svg b/studio-desktop/src/main/java/studio/flags/pc.svg new file mode 100644 index 000000000..a38dd212b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pc.svg @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pe.svg b/studio-desktop/src/main/java/studio/flags/pe.svg new file mode 100644 index 000000000..9ba4c6124 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pe.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pf.svg b/studio-desktop/src/main/java/studio/flags/pf.svg new file mode 100644 index 000000000..92b2803c5 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pf.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pg.svg b/studio-desktop/src/main/java/studio/flags/pg.svg new file mode 100644 index 000000000..8c8a2b8eb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pg.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ph.svg b/studio-desktop/src/main/java/studio/flags/ph.svg new file mode 100644 index 000000000..7ae39fec8 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ph.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pk.svg b/studio-desktop/src/main/java/studio/flags/pk.svg new file mode 100644 index 000000000..e71cd9261 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pk.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pl.svg b/studio-desktop/src/main/java/studio/flags/pl.svg new file mode 100644 index 000000000..8c43577b0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pl.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pm.svg b/studio-desktop/src/main/java/studio/flags/pm.svg new file mode 100644 index 000000000..950c6e8c0 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pm.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pn.svg b/studio-desktop/src/main/java/studio/flags/pn.svg new file mode 100644 index 000000000..0bae95e0d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pn.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pr.svg b/studio-desktop/src/main/java/studio/flags/pr.svg new file mode 100644 index 000000000..eb302ad45 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pr.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ps.svg b/studio-desktop/src/main/java/studio/flags/ps.svg new file mode 100644 index 000000000..2c10079c1 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ps.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pt.svg b/studio-desktop/src/main/java/studio/flags/pt.svg new file mode 100644 index 000000000..95ad6d79d --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pt.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/pw.svg b/studio-desktop/src/main/java/studio/flags/pw.svg new file mode 100644 index 000000000..ef6be7983 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/pw.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/py.svg b/studio-desktop/src/main/java/studio/flags/py.svg new file mode 100644 index 000000000..e7e1bced9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/py.svg @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/qa.svg b/studio-desktop/src/main/java/studio/flags/qa.svg new file mode 100644 index 000000000..897a21bca --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/qa.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/re.svg b/studio-desktop/src/main/java/studio/flags/re.svg new file mode 100644 index 000000000..41d87d938 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/re.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ro.svg b/studio-desktop/src/main/java/studio/flags/ro.svg new file mode 100644 index 000000000..e6cf0f6e1 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ro.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/rs.svg b/studio-desktop/src/main/java/studio/flags/rs.svg new file mode 100644 index 000000000..d10ebb3e4 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/rs.svg @@ -0,0 +1,296 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ru.svg b/studio-desktop/src/main/java/studio/flags/ru.svg new file mode 100644 index 000000000..f428b0ccb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ru.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/rw.svg b/studio-desktop/src/main/java/studio/flags/rw.svg new file mode 100644 index 000000000..3d484fd90 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/rw.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sa.svg b/studio-desktop/src/main/java/studio/flags/sa.svg new file mode 100644 index 000000000..fd6418eef --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sa.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sb.svg b/studio-desktop/src/main/java/studio/flags/sb.svg new file mode 100644 index 000000000..398c70847 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sb.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sc.svg b/studio-desktop/src/main/java/studio/flags/sc.svg new file mode 100644 index 000000000..2996bac45 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sc.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sd.svg b/studio-desktop/src/main/java/studio/flags/sd.svg new file mode 100644 index 000000000..0b9abdc8a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sd.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/se.svg b/studio-desktop/src/main/java/studio/flags/se.svg new file mode 100644 index 000000000..8f3f134d2 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/se.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sg.svg b/studio-desktop/src/main/java/studio/flags/sg.svg new file mode 100644 index 000000000..60625e97f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sg.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sh-ac.svg b/studio-desktop/src/main/java/studio/flags/sh-ac.svg new file mode 100644 index 000000000..85cd9d1c5 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sh-ac.svg @@ -0,0 +1,690 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sh-hl.svg b/studio-desktop/src/main/java/studio/flags/sh-hl.svg new file mode 100644 index 000000000..4cb199048 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sh-hl.svg @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sh-ta.svg b/studio-desktop/src/main/java/studio/flags/sh-ta.svg new file mode 100644 index 000000000..7933fc21b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sh-ta.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sh.svg b/studio-desktop/src/main/java/studio/flags/sh.svg new file mode 100644 index 000000000..2fd372750 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sh.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/si.svg b/studio-desktop/src/main/java/studio/flags/si.svg new file mode 100644 index 000000000..33a03c625 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/si.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sj.svg b/studio-desktop/src/main/java/studio/flags/sj.svg new file mode 100644 index 000000000..ecb9c796b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sj.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sk.svg b/studio-desktop/src/main/java/studio/flags/sk.svg new file mode 100644 index 000000000..d1868226c --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sk.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sl.svg b/studio-desktop/src/main/java/studio/flags/sl.svg new file mode 100644 index 000000000..b649f1bd5 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sl.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sm.svg b/studio-desktop/src/main/java/studio/flags/sm.svg new file mode 100644 index 000000000..30c249015 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sm.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sn.svg b/studio-desktop/src/main/java/studio/flags/sn.svg new file mode 100644 index 000000000..ff9cf2eb3 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sn.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/so.svg b/studio-desktop/src/main/java/studio/flags/so.svg new file mode 100644 index 000000000..4848dbe0b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/so.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sr.svg b/studio-desktop/src/main/java/studio/flags/sr.svg new file mode 100644 index 000000000..0ca359627 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sr.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ss.svg b/studio-desktop/src/main/java/studio/flags/ss.svg new file mode 100644 index 000000000..bb50fac15 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ss.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/st.svg b/studio-desktop/src/main/java/studio/flags/st.svg new file mode 100644 index 000000000..c5e7c5ce6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/st.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sv.svg b/studio-desktop/src/main/java/studio/flags/sv.svg new file mode 100644 index 000000000..14e98b058 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sv.svg @@ -0,0 +1,594 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sx.svg b/studio-desktop/src/main/java/studio/flags/sx.svg new file mode 100644 index 000000000..758f483c9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sx.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sy.svg b/studio-desktop/src/main/java/studio/flags/sy.svg new file mode 100644 index 000000000..39e63f7fb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sy.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/sz.svg b/studio-desktop/src/main/java/studio/flags/sz.svg new file mode 100644 index 000000000..12ae0cdc6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/sz.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tc.svg b/studio-desktop/src/main/java/studio/flags/tc.svg new file mode 100644 index 000000000..0b5af9811 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tc.svg @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/td.svg b/studio-desktop/src/main/java/studio/flags/td.svg new file mode 100644 index 000000000..8201312b6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/td.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tf.svg b/studio-desktop/src/main/java/studio/flags/tf.svg new file mode 100644 index 000000000..1ab7f6a8f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tf.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tg.svg b/studio-desktop/src/main/java/studio/flags/tg.svg new file mode 100644 index 000000000..32c28af4f --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tg.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/th.svg b/studio-desktop/src/main/java/studio/flags/th.svg new file mode 100644 index 000000000..35141d39a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/th.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tj.svg b/studio-desktop/src/main/java/studio/flags/tj.svg new file mode 100644 index 000000000..9232ec1d3 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tj.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tk.svg b/studio-desktop/src/main/java/studio/flags/tk.svg new file mode 100644 index 000000000..9ff92e5ee --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tl.svg b/studio-desktop/src/main/java/studio/flags/tl.svg new file mode 100644 index 000000000..4fbb245e9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tl.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tm.svg b/studio-desktop/src/main/java/studio/flags/tm.svg new file mode 100644 index 000000000..ac39386b8 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tm.svg @@ -0,0 +1,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tn.svg b/studio-desktop/src/main/java/studio/flags/tn.svg new file mode 100644 index 000000000..ab3e36e4b --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tn.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/to.svg b/studio-desktop/src/main/java/studio/flags/to.svg new file mode 100644 index 000000000..3f1b60079 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/to.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tr.svg b/studio-desktop/src/main/java/studio/flags/tr.svg new file mode 100644 index 000000000..0fe9017c9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tr.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tt.svg b/studio-desktop/src/main/java/studio/flags/tt.svg new file mode 100644 index 000000000..0f7f26e7e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tt.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tv.svg b/studio-desktop/src/main/java/studio/flags/tv.svg new file mode 100644 index 000000000..098b91610 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tv.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tw.svg b/studio-desktop/src/main/java/studio/flags/tw.svg new file mode 100644 index 000000000..83f4e442e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tw.svg @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/tz.svg b/studio-desktop/src/main/java/studio/flags/tz.svg new file mode 100644 index 000000000..846cbb5ad --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/tz.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ua.svg b/studio-desktop/src/main/java/studio/flags/ua.svg new file mode 100644 index 000000000..7ceb89463 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ua.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ug.svg b/studio-desktop/src/main/java/studio/flags/ug.svg new file mode 100644 index 000000000..a82a8fcf6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ug.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/um.svg b/studio-desktop/src/main/java/studio/flags/um.svg new file mode 100644 index 000000000..b8d4502e6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/um.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/un.svg b/studio-desktop/src/main/java/studio/flags/un.svg new file mode 100644 index 000000000..322569d14 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/un.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/us.svg b/studio-desktop/src/main/java/studio/flags/us.svg new file mode 100644 index 000000000..a7220476a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/us.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/uy.svg b/studio-desktop/src/main/java/studio/flags/uy.svg new file mode 100644 index 000000000..f6b08b280 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/uy.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/uz.svg b/studio-desktop/src/main/java/studio/flags/uz.svg new file mode 100644 index 000000000..3385bc5aa --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/uz.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/va.svg b/studio-desktop/src/main/java/studio/flags/va.svg new file mode 100644 index 000000000..9348ad238 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/va.svg @@ -0,0 +1,190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/vc.svg b/studio-desktop/src/main/java/studio/flags/vc.svg new file mode 100644 index 000000000..21d41a805 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/vc.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ve.svg b/studio-desktop/src/main/java/studio/flags/ve.svg new file mode 100644 index 000000000..665135ba6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ve.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/vg.svg b/studio-desktop/src/main/java/studio/flags/vg.svg new file mode 100644 index 000000000..cfcbbba42 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/vg.svg @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/vi.svg b/studio-desktop/src/main/java/studio/flags/vi.svg new file mode 100644 index 000000000..081f8c6c9 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/vi.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/vn.svg b/studio-desktop/src/main/java/studio/flags/vn.svg new file mode 100644 index 000000000..49a68f02e --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/vn.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/vu.svg b/studio-desktop/src/main/java/studio/flags/vu.svg new file mode 100644 index 000000000..0e695b95a --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/vu.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/wf.svg b/studio-desktop/src/main/java/studio/flags/wf.svg new file mode 100644 index 000000000..5ba64e4da --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/wf.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ws.svg b/studio-desktop/src/main/java/studio/flags/ws.svg new file mode 100644 index 000000000..ab08fdb91 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ws.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/xk.svg b/studio-desktop/src/main/java/studio/flags/xk.svg new file mode 100644 index 000000000..28bdeadbd --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/xk.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/xx.svg b/studio-desktop/src/main/java/studio/flags/xx.svg new file mode 100644 index 000000000..5a44cb701 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/xx.svg @@ -0,0 +1,4 @@ + + + + diff --git a/studio-desktop/src/main/java/studio/flags/ye.svg b/studio-desktop/src/main/java/studio/flags/ye.svg new file mode 100644 index 000000000..2ccb23bf6 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/ye.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/yt.svg b/studio-desktop/src/main/java/studio/flags/yt.svg new file mode 100644 index 000000000..41a4408cb --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/yt.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/za.svg b/studio-desktop/src/main/java/studio/flags/za.svg new file mode 100644 index 000000000..397696eda --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/za.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/zm.svg b/studio-desktop/src/main/java/studio/flags/zm.svg new file mode 100644 index 000000000..a2084fb28 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/zm.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/studio-desktop/src/main/java/studio/flags/zw.svg b/studio-desktop/src/main/java/studio/flags/zw.svg new file mode 100644 index 000000000..98e1a42d4 --- /dev/null +++ b/studio-desktop/src/main/java/studio/flags/zw.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + From ca5b30e7580faa33d583c11ef9f75dac81a65547 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 13:55:44 +0200 Subject: [PATCH 14/21] fixing age translation --- .../src/main/java/studio/JsonPackCell.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/studio-desktop/src/main/java/studio/JsonPackCell.java b/studio-desktop/src/main/java/studio/JsonPackCell.java index abf9f77a1..42a53a4dc 100644 --- a/studio-desktop/src/main/java/studio/JsonPackCell.java +++ b/studio-desktop/src/main/java/studio/JsonPackCell.java @@ -198,8 +198,16 @@ public Component getListCellRendererComponent(JList list, Js }); components.stream().filter( (c) -> "age".equals(c.getName())).findFirst().ifPresent( ( c) -> { - if ( !(value.getAgeMin() == 0 && value.getAgeMax() == 0) ) { - String strAge = value.getAgeMax() == -1 ? substituteParameters(localization.getString("JsonPackCell.age1"), value.getAgeMin()) : substituteParameters(localization.getString("JsonPackCell.age3"), value.getAgeMin(), value.getAgeMax()); + if ( !(value.getAgeMin() == 0 && value.getAgeMax() == 0) ) { + String strAge = ""; + if ( value.getAgeMin() == -1 && value.getAgeMax() != -1 ) { + strAge = substituteParameters(localization.getString("JsonPackCell.age2"), value.getAgeMax()); + } else if ( value.getAgeMin() != -1 && value.getAgeMax() == -1 ) { + strAge = substituteParameters(localization.getString("JsonPackCell.age1"), value.getAgeMin()); + } else if ( value.getAgeMin() != -1 && value.getAgeMax() != -1 ) { + strAge = substituteParameters(localization.getString("JsonPackCell.age3"), value.getAgeMin(), value.getAgeMax()); + + } ((JLabel)c).setText(strAge); } else { ((JLabel)c).setText(""); From 5ed488c91f987be4c265820c7be8abdfed5abbc5 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 13:56:07 +0200 Subject: [PATCH 15/21] new filtering capabilities --- studio-desktop/src/main/java/studio/GUI.java | 146 +++++++++++++++++- .../localization/Translation.properties | 2 + .../localization/Translation_fr_FR.properties | 2 + 3 files changed, 149 insertions(+), 1 deletion(-) diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index 92f888f56..fd730f2aa 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -40,17 +40,22 @@ import java.util.Locale; import java.util.Optional; import java.util.ResourceBundle; +import java.util.Set; import java.util.UUID; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import java.util.stream.IntStream; +import java.util.stream.Stream; import javax.swing.BoxLayout; +import javax.swing.ComboBoxModel; +import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListModel; import javax.swing.DropMode; import javax.swing.JButton; import javax.swing.JCheckBox; +import javax.swing.JComboBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JLabel; @@ -62,13 +67,18 @@ import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JScrollPane; +import javax.swing.JSpinner; import javax.swing.JSplitPane; import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; +import javax.swing.SpinnerModel; +import javax.swing.SpinnerNumberModel; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.border.TitledBorder; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; @@ -100,6 +110,7 @@ import studio.driver.model.raw.RawStoryPackInfos; import studio.driver.raw.LibUsbMassStorageHelper; import studio.driver.raw.RawStoryTellerAsyncDriver; +import javax.swing.SwingConstants; public class GUI { @@ -149,6 +160,13 @@ public class GUI { private PlaceholderTextField librarySearchTextField; private PlaceholderTextField deviceSearchTextField; private JCheckBox displayOnlyNotOnDeviceCheckBox; + private JPanel panel_1; + private JComboBox languageFilterComboBox; + private JLabel lblNewLabel; + private JSpinner spinner; + private JLabel lblNewLabel_1; + private JSpinner spinner_1; + private DefaultComboBoxModel availableLanguagesModel; /** * Launch the application. @@ -220,6 +238,9 @@ private void initializeLunii() { library.getPacks().thenAcceptAsync((List packs) -> { libraryPacksModel.addAll(packs); btnRefreshLibrary.setEnabled(true); + Set languages = packs.stream().map( (JsonPack p) -> p.getLocalizedInfos().keySet().iterator().next()).collect(Collectors.toSet()); + availableLanguagesModel.removeAllElements(); + availableLanguagesModel.addAll(languages); }); fsDriver = new FsStoryTellerAsyncDriver(false); @@ -351,6 +372,34 @@ private void refreshFreeSpaceOnDevice() { } } + + private void filterLibrary() { + String language = (String)languageFilterComboBox.getSelectedItem(); + int from = (int)spinner.getValue(); + int to = (int)spinner_1.getValue(); + + library.getPacks().thenAcceptAsync( (List packs) -> { + Stream stream = packs.stream(); + if ( language != null ) { + stream = stream.filter( (JsonPack pack) -> { + return pack.getLocalizedInfos().keySet().contains(language); + }); + } + if ( from > 0 ) { + stream = stream.filter( (JsonPack pack) -> pack.getAgeMin() >= from); + } + if ( to > 0 ) { + stream = stream.filter( (JsonPack pack) -> pack.getAgeMax() == -1 ? pack.getAgeMin() <= to : pack.getAgeMax() <= to); + } + libraryPacksModel.clear(); + libraryPacksModel.addAll(stream.collect(Collectors.toList())); + + + }); + + + } + /** * Initialize the contents of the frame. */ @@ -1111,6 +1160,14 @@ public void actionPerformed(ActionEvent e) { libraryPacksModel.clear(); library.refreshDatabase().thenRunAsync(() -> { library.getPacks().thenAcceptAsync((List packs) -> { + Set languages = packs.stream().map( (JsonPack p) -> { + return p.getLocalizedInfos() == null || p.getLocalizedInfos().isEmpty() ? null : p.getLocalizedInfos().keySet().iterator().next(); + }).collect(Collectors.toSet()); + if ( !languages.contains(null) ) { + languages.add(null); + } + availableLanguagesModel.removeAllElements(); + availableLanguagesModel.addAll(languages); libraryPacksModel.addAll(packs); btnRefreshLibrary.setEnabled(true); @@ -1154,9 +1211,46 @@ public void actionPerformed(ActionEvent e) { gbc_libraryPacksSummaryLabel.gridy = 0; panel_6.add(libraryPacksSummaryLabel, gbc_libraryPacksSummaryLabel); + panel_1 = new JPanel(); + libraryListPanel.add(panel_1, BorderLayout.NORTH); + GridBagLayout gbl_panel_1 = new GridBagLayout(); + //gbl_panel_1.columnWidths = new int[] {51, 52, 60, 60, 60, 60, 30}; + //gbl_panel_1.rowHeights = new int[]{27, 0}; + gbl_panel_1.columnWeights = new double[]{0.0, 1.0, 0.0, 0.0, 0.0, 0.0}; + gbl_panel_1.rowWeights = new double[]{0.0}; + panel_1.setLayout(gbl_panel_1); + + + availableLanguagesModel = new DefaultComboBoxModel(); + languageFilterComboBox = new JComboBox(availableLanguagesModel); + languageFilterComboBox.setRenderer(new LanguagesCellRenderer()); + languageFilterComboBox.setMinimumSize(new Dimension(70, 20)); + languageFilterComboBox.setPreferredSize(new Dimension(70, 20)); + GridBagConstraints gbc_comboBox = new GridBagConstraints(); + gbc_comboBox.anchor = GridBagConstraints.WEST; + gbc_comboBox.insets = new Insets(0, 0, 0, 5); + gbc_comboBox.gridx = 0; + gbc_comboBox.gridy = 0; + panel_1.add(languageFilterComboBox, gbc_comboBox); + languageFilterComboBox.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(ActionEvent e) { + filterLibrary(); + + } + }); + librarySearchTextField = new PlaceholderTextField(); + GridBagConstraints gbc_librarySearchTextField = new GridBagConstraints(); + gbc_librarySearchTextField.weightx = 10.0; + gbc_librarySearchTextField.fill = GridBagConstraints.HORIZONTAL; + gbc_librarySearchTextField.anchor = GridBagConstraints.NORTH; + gbc_librarySearchTextField.insets = new Insets(0, 0, 0, 5); + gbc_librarySearchTextField.gridx = 1; + gbc_librarySearchTextField.gridy = 0; + panel_1.add(librarySearchTextField, gbc_librarySearchTextField); librarySearchTextField.setPlaceHolder(localization.getString("Library.search")); - libraryListPanel.add(librarySearchTextField, BorderLayout.NORTH); librarySearchTextField.addKeyListener(new KeyAdapter() { @Override public void keyTyped(KeyEvent e) { @@ -1181,6 +1275,56 @@ public void keyTyped(KeyEvent e) { } } }); + + lblNewLabel = new JLabel(localization.getString("Library.searchFrom")); + lblNewLabel.setHorizontalAlignment(SwingConstants.TRAILING); + GridBagConstraints gbc_lblNewLabel = new GridBagConstraints(); + gbc_lblNewLabel.anchor = GridBagConstraints.EAST; + //gbc_lblNewLabel.anchor = GridBagConstraints.WEST; + gbc_lblNewLabel.insets = new Insets(0, 0, 0, 5); + gbc_lblNewLabel.gridx = 2; + gbc_lblNewLabel.gridy = 0; + panel_1.add(lblNewLabel, gbc_lblNewLabel); + + spinner = new JSpinner(new SpinnerNumberModel(0, 0, 13, 1)); + GridBagConstraints gbc_spinner = new GridBagConstraints(); + gbc_spinner.anchor = GridBagConstraints.NORTHEAST; + gbc_spinner.insets = new Insets(0, 0, 0, 5); + gbc_spinner.gridx = 3; + gbc_spinner.gridy = 0; + panel_1.add(spinner, gbc_spinner); + spinner.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + filterLibrary(); + + } + }); + + lblNewLabel_1 = new JLabel(localization.getString("Library.searchTo")); + GridBagConstraints gbc_lblNewLabel_1 = new GridBagConstraints(); + gbc_lblNewLabel_1.anchor = GridBagConstraints.EAST; + gbc_lblNewLabel_1.insets = new Insets(0, 0, 0, 5); + gbc_lblNewLabel_1.gridx = 4; + gbc_lblNewLabel_1.gridy = 0; + panel_1.add(lblNewLabel_1, gbc_lblNewLabel_1); + + spinner_1 = new JSpinner(new SpinnerNumberModel(0, 0, 13, 1)); + GridBagConstraints gbc_spinner_1 = new GridBagConstraints(); + gbc_spinner_1.insets = new Insets(0, 0, 0, 5); + gbc_spinner_1.anchor = GridBagConstraints.NORTHEAST; + gbc_spinner_1.gridx = 5; + gbc_spinner_1.gridy = 0; + panel_1.add(spinner_1, gbc_spinner_1); + spinner_1.addChangeListener(new ChangeListener() { + + @Override + public void stateChanged(ChangeEvent e) { + filterLibrary(); + + } + }); statusPanel = new JPanel(); panel.add(statusPanel, BorderLayout.SOUTH); diff --git a/studio-desktop/src/main/java/studio/localization/Translation.properties b/studio-desktop/src/main/java/studio/localization/Translation.properties index 64cb2fb4d..4d085f387 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation.properties @@ -26,6 +26,8 @@ File.quit=Quit File.export=Export... Export.SaveFile=Save file Library.search=Search +Library.searchFrom=From +Library.searchTo=To Library.changePath=Change library path... Library.ChooseLibraryFolder=Choose file Import.ChooseImportEntry=Choose file or folder diff --git a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties index 2fff3ae6a..51332d301 100644 --- a/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties +++ b/studio-desktop/src/main/java/studio/localization/Translation_fr_FR.properties @@ -26,6 +26,8 @@ File.quit=Quitter File.export=Exporter... Export.SaveFile=Sauvegarder le fichier Library.search=Rechercher +Library.searchFrom=De +Library.searchTo=À Library.changePath=Changer le répertoire de la librairie... Library.ChooseLibraryFolder=Choisir le répertoire Import.ChooseImportEntry=Choisissez un fichier ou répertoire... From 81427432c54b2e2434009b9786028fa1d688e166 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 13:56:21 +0200 Subject: [PATCH 16/21] adding svg flags --- studio-desktop/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/studio-desktop/pom.xml b/studio-desktop/pom.xml index 6f88f55af..9349a3a11 100644 --- a/studio-desktop/pom.xml +++ b/studio-desktop/pom.xml @@ -101,6 +101,11 @@ fastexcel 0.15.3 + + org.apache.xmlgraphics + batik-all + 1.17 + @@ -108,6 +113,7 @@ src/main/java **/*.properties + **/*.svg From ffe16de8a110daec57eaff2c60451de151fb1423 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 13:56:55 +0200 Subject: [PATCH 17/21] removing undesired files --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 102e0975d..c6c678662 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ *.log web-ui/javascript/build web-ui/javascript/report.*.json + +**/.DS_Store \ No newline at end of file From 1b0d9c3ae7d40e1b12f84370e677d1b01c480e7d Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 15:56:24 +0200 Subject: [PATCH 18/21] macos build feature --- .../Lunii-Transfert.app/Contents/Info.plist | 26 +++++++++++++++++++ studio-desktop/build_macos_app.sh | 18 +++++++++++++ studio-desktop/pom.xml | 17 ++++++++++++ studio-desktop/src/main/resources/studio.sh | 9 ++++--- 4 files changed, 66 insertions(+), 4 deletions(-) create mode 100755 studio-desktop/Lunii-Transfert.app/Contents/Info.plist create mode 100755 studio-desktop/build_macos_app.sh diff --git a/studio-desktop/Lunii-Transfert.app/Contents/Info.plist b/studio-desktop/Lunii-Transfert.app/Contents/Info.plist new file mode 100755 index 000000000..a50d4bd12 --- /dev/null +++ b/studio-desktop/Lunii-Transfert.app/Contents/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleName + Lunii Transfert + + CFBundleExecutable + studio.sh + + CFBundleIconFile + lunii.png + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundlePackageType + APPL + + CFBundleSignature + ???? + + CFBundleIdentifier + studio.GUI + + diff --git a/studio-desktop/build_macos_app.sh b/studio-desktop/build_macos_app.sh new file mode 100755 index 000000000..59417c394 --- /dev/null +++ b/studio-desktop/build_macos_app.sh @@ -0,0 +1,18 @@ +#!/bin/bash + + +cp -r Lunii-Transfert.app target/ +cp target/studio.sh target/Lunii-Transfert.app/Contents/MacOS +cp target/lunii.png target/Lunii-Transfert.app/Contents/Resources +cp -r target/lib/ target/Lunii-Transfert.app/Contents/Resources/Java/lib +cp libusb4java-1.3.0-darwin-aarch64.jar target/Lunii-Transfert.app/Contents/Resources/Java/lib/ +cp target/$1.jar target/Lunii-Transfert.app/Contents/Resources/Java + +rm -rf /tmp/buildlunii +mkdir -p /tmp/buildlunii +cp -r target/Lunii-Transfert.app /tmp/buildlunii +ln -s /Applications/ /tmp/buildlunii/Applications + +hdiutil create -fs HFS+ -srcfolder "/tmp/buildlunii" -volname Lunii-Transfert target/Lunii-Transfert.dmg + +rm -rf /tmp/buildlunii \ No newline at end of file diff --git a/studio-desktop/pom.xml b/studio-desktop/pom.xml index 9349a3a11..983015ab1 100644 --- a/studio-desktop/pom.xml +++ b/studio-desktop/pom.xml @@ -156,6 +156,23 @@ + + exec-maven-plugin + org.codehaus.mojo + + + bundle_macosapp + package + + exec + + + ${basedir}/build_macos_app.sh + ${project.build.finalName} + + + + org.apache.maven.plugins maven-assembly-plugin diff --git a/studio-desktop/src/main/resources/studio.sh b/studio-desktop/src/main/resources/studio.sh index 414198da1..91b118867 100755 --- a/studio-desktop/src/main/resources/studio.sh +++ b/studio-desktop/src/main/resources/studio.sh @@ -1,12 +1,13 @@ #!/bin/bash +ARCH="$(uname -s)" APP_PATH=`dirname $0` VERSION=${project.build.finalName} -STUDIO_CP=$APP_PATH/lib/*:$APP_PATH:$APP_PATH/$VERSION.jar -if [ "$(uname)" == "Darwin" ]; then - java -Xdock:description="Studio" -Xdock:icon=$APP_PATH/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI +if [ "${ARCH}" == "Darwin" ]; then + STUDIO_CP=$APP_PATH/lib/*:$APP_PATH/$VERSION.jar:$APP_PATH/../Resources/Java/lib/*:$APP_PATH/../Resources/Java/$VERSION.jar + java -Dcom.apple.mrj.application.apple.menu.about.name="Lunii Transfert" -Dapple.awt.application.name="Lunii Transfert" -Xdock:description="Lunii Transfert" -Xdock:icon=$APP_PATH/../Resources/lunii.png -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI else + STUDIO_CP=$APP_PATH/lib/*:$APP_PATH:$APP_PATH/$VERSION.jar java -cp $STUDIO_CP -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager studio.GUI fi - From d8f297b3c62f72b94c74e81fc398e57387bebdbd Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 16:26:22 +0200 Subject: [PATCH 19/21] add persisted path to the library --- studio-desktop/prefs.ini | 3 ++ studio-desktop/src/main/java/studio/GUI.java | 34 ++++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) create mode 100644 studio-desktop/prefs.ini diff --git a/studio-desktop/prefs.ini b/studio-desktop/prefs.ini new file mode 100644 index 000000000..b22a7bbe4 --- /dev/null +++ b/studio-desktop/prefs.ini @@ -0,0 +1,3 @@ +#auto-generated +#Thu Jul 25 16:25:40 CEST 2024 +libraryPath=/Users/horfee/Documents/studio-library diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index fd730f2aa..42d065026 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -26,6 +26,7 @@ import java.awt.event.MouseEvent; import java.awt.event.WindowEvent; import java.io.File; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -39,6 +40,7 @@ import java.util.List; import java.util.Locale; import java.util.Optional; +import java.util.Properties; import java.util.ResourceBundle; import java.util.Set; import java.util.UUID; @@ -49,7 +51,6 @@ import java.util.stream.Stream; import javax.swing.BoxLayout; -import javax.swing.ComboBoxModel; import javax.swing.DefaultComboBoxModel; import javax.swing.DefaultListModel; import javax.swing.DropMode; @@ -72,8 +73,8 @@ import javax.swing.JTextField; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; -import javax.swing.SpinnerModel; import javax.swing.SpinnerNumberModel; +import javax.swing.SwingConstants; import javax.swing.TransferHandler; import javax.swing.UIManager; import javax.swing.border.TitledBorder; @@ -110,7 +111,6 @@ import studio.driver.model.raw.RawStoryPackInfos; import studio.driver.raw.LibUsbMassStorageHelper; import studio.driver.raw.RawStoryTellerAsyncDriver; -import javax.swing.SwingConstants; public class GUI { @@ -232,7 +232,20 @@ private CompletableFuture> loadPacksFromDevice() { } private void initializeLunii() { - library = Library.getInstance(System.getProperty("user.home")); + String libraryFolder = System.getProperty("user.home"); + if ( new File("./prefs.ini").exists()) { + Properties prop = new java.util.Properties(); + try { + prop.load(new FileInputStream(new File("./prefs.ini"))); + } catch (IOException e) { + } + libraryFolder = prop.getProperty("libraryPath"); + if ( libraryFolder == null ) { + libraryFolder = System.getProperty("user.home"); + } + + } + library = Library.getInstance(libraryFolder); libraryPathLabel.setText("Path: " + library.getLibraryPath()); library.getPacks().thenAcceptAsync((List packs) -> { @@ -1397,9 +1410,18 @@ public void actionPerformed(ActionEvent e) { chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); chooser.setAcceptAllFileFilterUsed(false); if (chooser.showOpenDialog(frmLuniiTransfer) == JFileChooser.APPROVE_OPTION) { - library = Library.getInstance(chooser.getSelectedFile().getAbsolutePath()); + String path = chooser.getSelectedFile().getAbsolutePath(); + Properties prop = new java.util.Properties(); + prop.setProperty("libraryPath", path); + try(FileOutputStream fos = new FileOutputStream(new File("./prefs.ini"))) { + prop.store(fos, "auto-generated"); + } catch (IOException e1) { + e1.printStackTrace(); + } + + library = Library.getInstance(path); btnRefreshLibrary.doClick(); - libraryPathLabel.setText("Path : " + library.getLibraryPath()); + libraryPathLabel.setText(localization.getString("Library.infoPath").replace("{}", library.getLibraryPath())); } } }); From 89cffca4afa58c76ac13d01831cf4cbd3eb5c2d3 Mon Sep 17 00:00:00 2001 From: horfee Date: Thu, 25 Jul 2024 16:48:38 +0200 Subject: [PATCH 20/21] adding persistence of library path --- studio-desktop/pom.xml | 5 ++++ studio-desktop/src/main/java/studio/GUI.java | 25 +++++++++----------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/studio-desktop/pom.xml b/studio-desktop/pom.xml index 983015ab1..f969d0b6c 100644 --- a/studio-desktop/pom.xml +++ b/studio-desktop/pom.xml @@ -23,6 +23,11 @@ studio-driver ${project.parent.version} + + net.harawata + appdirs + 1.2.2 + com.google.code.gson gson diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index 42d065026..e8f23a0a8 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -99,6 +99,7 @@ import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.usb4java.Device; +import net.harawata.appdirs.AppDirsFactory; import studio.database.JsonPack; import studio.database.Library; import studio.driver.event.DeviceHotplugEventListener; @@ -114,17 +115,6 @@ public class GUI { -// public class StoryPackInfosAndMetadata { -// protected FsStoryPackInfos pack; -// protected StoryPackMetadata metadata; -// -// protected StoryPackInfosAndMetadata(FsStoryPackInfos pack, StoryPackMetadata metadata) { -// this.pack = pack; -// this.metadata = metadata; -// } -// -// } - private JFrame frmLuniiTransfer; private JTextField serialNumberTextBox; private JTextField uUIDTextBox; @@ -233,10 +223,11 @@ private CompletableFuture> loadPacksFromDevice() { private void initializeLunii() { String libraryFolder = System.getProperty("user.home"); - if ( new File("./prefs.ini").exists()) { + File prefsFile = new File(AppDirsFactory.getInstance().getUserConfigDir("Lunii-Transfert", "0.4.1", "horfee") + "/prefs.ini"); + if ( prefsFile.exists()) { Properties prop = new java.util.Properties(); try { - prop.load(new FileInputStream(new File("./prefs.ini"))); + prop.load(new FileInputStream(prefsFile)); } catch (IOException e) { } libraryFolder = prop.getProperty("libraryPath"); @@ -1398,6 +1389,7 @@ public void actionPerformed(ActionEvent e) { } }); + JMenuItem changeLibraryPathMenuItem = new JMenuItem(localization.getString("Library.changePath")); @@ -1413,7 +1405,12 @@ public void actionPerformed(ActionEvent e) { String path = chooser.getSelectedFile().getAbsolutePath(); Properties prop = new java.util.Properties(); prop.setProperty("libraryPath", path); - try(FileOutputStream fos = new FileOutputStream(new File("./prefs.ini"))) { + File file = new File(AppDirsFactory.getInstance().getUserConfigDir("Lunii-Transfert", "0.4.1", "horfee")); + if ( !file.exists()) { + file.mkdirs(); + } + file = new File(file.getAbsolutePath() + "/prefs.ini"); + try(FileOutputStream fos = new FileOutputStream( file )) { prop.store(fos, "auto-generated"); } catch (IOException e1) { e1.printStackTrace(); From fe2b08830e6b07a3af330f8842299d1dbefa996f Mon Sep 17 00:00:00 2001 From: horfee Date: Fri, 26 Jul 2024 13:47:51 +0200 Subject: [PATCH 21/21] fix language filter --- studio-desktop/src/main/java/studio/GUI.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/studio-desktop/src/main/java/studio/GUI.java b/studio-desktop/src/main/java/studio/GUI.java index e8f23a0a8..7a188569f 100644 --- a/studio-desktop/src/main/java/studio/GUI.java +++ b/studio-desktop/src/main/java/studio/GUI.java @@ -242,7 +242,14 @@ private void initializeLunii() { library.getPacks().thenAcceptAsync((List packs) -> { libraryPacksModel.addAll(packs); btnRefreshLibrary.setEnabled(true); - Set languages = packs.stream().map( (JsonPack p) -> p.getLocalizedInfos().keySet().iterator().next()).collect(Collectors.toSet()); + + Set languages = packs.stream().map( (JsonPack p) -> { + return p.getLocalizedInfos() == null || p.getLocalizedInfos().isEmpty() ? null : p.getLocalizedInfos().keySet().iterator().next(); + }).collect(Collectors.toSet()); + if ( !languages.contains(null) ) { + languages.add(null); + } + availableLanguagesModel.removeAllElements(); availableLanguagesModel.addAll(languages); });