<commit_before>/*
 * Copyright 2011 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.eknet.swing.imagecomponent;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import javax.imageio.ImageIO;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.OverlayLayout;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * An input component for images.
 * <p/>
 * It consists of the following:
 * <ul>
 * <li>two text fields, one for the image url and one for an optional title for name</li>
 * <li>a preview button, that shows the image. onclick a open-file-dialog is presented to choose a file
 * from the file system</li>
 * <li>optional, a set of predefined images can be specified. If so, a small button opens a
 * component that allows the user to choose a image.</li>
 * <li>a button to reset the form</li>
 * </ul>
 * It supports scaling the image to a specified height/width.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @since 01.10.11 15:24
 */
public class ImageInput extends JPanel {

  private static final Logger log = LoggerFactory.getLogger(ImageInput.class);

  private JPanel root;
  private JButton previewButton;
  private JTextField resourceField;
  private JTextField nameField;
  private JPanel previewPanel;
  private JButton proposalsButton;
  private JButton resetButton;
  private JLabel messageLabel;

  private static final ImageIcon folderIcon = new ImageIcon(ImageInput.class.getResource("folder.png"));
  private static final ImageIcon resetIcon = new ImageIcon(ImageInput.class.getResource("arrow_undo.png"));
  private static final ImageIcon imagesIcon = new ImageIcon(ImageInput.class.getResource("images.png"));
  private static final ImageIcon successIcon = new ImageIcon(ImageInput.class.getResource("tick.png"));
  private static final ImageIcon errorIcon = new ImageIcon(ImageInput.class.getResource("error.png"));


  private Set<URL> proposals;
  private Dimension previewSize = new Dimension(50, 50);
  private final Color normalMessageColor;
  private Color errorMessageColor = Color.red;
  private IconViewer iconViewer = new IconViewer();
  private JDialog dialog;
  private boolean documentListenerMuted = false;

  private JComponent glassPane = new SimpleGlassPane();

  private final MouseAdapter emptyMouseListener = new MouseAdapter() {};
  private final KeyAdapter emptyKeyListener = new KeyAdapter() {};

  private ImageValue image;

  public ImageInput() {
    setLayout(new OverlayLayout(this));
    this.normalMessageColor = messageLabel.getForeground();

    messageLabel.setFont(messageLabel.getFont().deriveFont(10f));

    iconViewer.addListSelectionListener(new ListSelectionListener() {
      @Override
      public void valueChanged(ListSelectionEvent e) {
        if (!e.getValueIsAdjusting()) {
          URL url = (URL) iconViewer.getIconList().getSelectedValue();
          if (url != null) {
            ImageValue value = createNewOrCopy();
            value.setImageResource(url);
            setImage(value);
          }
          if (dialog != null) {
            dialog.setVisible(false);
          }
        }
      }
    });

    previewButton.setIcon(folderIcon);
    previewButton.setText("...");
    previewButton.addActionListener(newOpenImageAction());
    previewButton.setBackground(Color.white);
    previewButton.setToolTipText(getOpenButtonTooltip());

    proposalsButton.setIcon(imagesIcon);
    proposalsButton.setText(null);
    proposalsButton.setVisible(false);
    proposalsButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if (dialog == null) {
          Window parent = Utils.findWindow(proposalsButton);
          dialog = new JDialog(parent, "Proposals");
          dialog.getContentPane().setLayout(new BorderLayout());
          dialog.getContentPane().add(iconViewer, BorderLayout.CENTER);
        }
        Rectangle bounds = new Rectangle();
        Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
        bounds.x = mouseLoc.x;
        bounds.y = mouseLoc.y;
        bounds.width = 350;
        bounds.height = 250;
        dialog.setBounds(bounds);
        dialog.setVisible(true);
      }
    });

    resetButton.setIcon(resetIcon);
    resetButton.setText(null);
    resetButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setImage(null);
      }
    });

    resourceField.addKeyListener(new KeyAdapter() {
      @Override
      public void keyTyped(KeyEvent e) {
        if (e.getKeyChar() == KeyEvent.VK_ENTER) {
          String url = resourceField.getText();
          if (url == null || "".equals(url.trim())) {
            setImage(null);
          } else {
            ImageValue value = createNewOrCopy();
            try {
              if (!url.contains(":/")) {
                url = new File(url).toURI().toURL().toString();<commit_msg>close iconviewer dialog when hitting ESC<commit_after>/*
 * Copyright 2011 <NAME>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.eknet.swing.imagecomponent;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dialog;
import java.awt.Dimension;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.image.BufferedImage;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.OverlayLayout;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * An input component for images.
 * <p/>
 * It consists of the following:
 * <ul>
 * <li>two text fields, one for the image url and one for an optional title for name</li>
 * <li>a preview button, that shows the image. onclick a open-file-dialog is presented to choose a file
 * from the file system</li>
 * <li>optional, a set of predefined images can be specified. If so, a small button opens a
 * component that allows the user to choose a image.</li>
 * <li>a button to reset the form</li>
 * </ul>
 * It supports scaling the image to a specified height/width.
 *
 * @author <a href="mailto:<EMAIL>"><NAME></a>
 * @since 01.10.11 15:24
 */
public class ImageInput extends JPanel {

  private static final Logger log = LoggerFactory.getLogger(ImageInput.class);

  private JPanel root;
  private JButton previewButton;
  private JTextField resourceField;
  private JTextField nameField;
  private JPanel previewPanel;
  private JButton proposalsButton;
  private JButton resetButton;
  private JLabel messageLabel;

  private static final ImageIcon folderIcon = new ImageIcon(ImageInput.class.getResource("folder.png"));
  private static final ImageIcon resetIcon = new ImageIcon(ImageInput.class.getResource("arrow_undo.png"));
  private static final ImageIcon imagesIcon = new ImageIcon(ImageInput.class.getResource("images.png"));
  private static final ImageIcon successIcon = new ImageIcon(ImageInput.class.getResource("tick.png"));
  private static final ImageIcon errorIcon = new ImageIcon(ImageInput.class.getResource("error.png"));


  private Set<URL> proposals;
  private Dimension previewSize = new Dimension(50, 50);
  private final Color normalMessageColor;
  private Color errorMessageColor = Color.red;
  private IconViewer iconViewer = new IconViewer();
  private JDialog dialog;
  private boolean documentListenerMuted = false;

  private JComponent glassPane = new SimpleGlassPane();

  private final MouseAdapter emptyMouseListener = new MouseAdapter() {};
  private final KeyAdapter emptyKeyListener = new KeyAdapter() {};

  private ImageValue image;

  public ImageInput() {
    setLayout(new OverlayLayout(this));
    this.normalMessageColor = messageLabel.getForeground();

    messageLabel.setFont(messageLabel.getFont().deriveFont(10f));

    iconViewer.addListSelectionListener(new ListSelectionListener() {
      @Override
      public void valueChanged(ListSelectionEvent e) {
        if (!e.getValueIsAdjusting()) {
          URL url = (URL) iconViewer.getIconList().getSelectedValue();
          if (url != null) {
            ImageValue value = createNewOrCopy();
            value.setImageResource(url);
            setImage(value);
          }
          if (dialog != null) {
            dialog.setVisible(false);
          }
        }
      }
    });

    previewButton.setIcon(folderIcon);
    previewButton.setText("...");
    previewButton.addActionListener(newOpenImageAction());
    previewButton.setBackground(Color.white);
    previewButton.setToolTipText(getOpenButtonTooltip());

    proposalsButton.setIcon(imagesIcon);
    proposalsButton.setText(null);
    proposalsButton.setVisible(false);
    proposalsButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if (dialog == null) {
          Window parent = Utils.findWindow(proposalsButton);
          dialog = new JDialog(parent, "Proposals", Dialog.ModalityType.APPLICATION_MODAL) {
            @Override
            protected JRootPane createRootPane() {
              JRootPane rootPane = super.createRootPane();
              KeyStroke escStroke = KeyStroke.getKeyStroke("ESCAPE");
              InputMap map = rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);

              map.put(escStroke, "ESCAPE");
              rootPane.getActionMap().put("ESCAPE", new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent e) {
                  dialog.setVisible(false);
                }
              });
              return rootPane;
            }
          };
          dialog.getContentPane().setLayout(new BorderLayout());
          dialog.getContentPane().add(iconViewer, BorderLayout.CENTER);
        }
        Rectangle bounds = new Rectangle();
        Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
        bounds.x = mouseLoc.x;
        bounds.y = mouseLoc.y;
        bounds.width = 350;
        bounds.height = 250;
        dialog.setBounds(bounds);
        dialog.setVisible(!dialog.isVisible());
      }
    });

    resetButton.setIcon(resetIcon);
    resetButton.setText(null);
    resetButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        setImage(null);
      }
    });

    resourceField.addKeyListener(new KeyAdapter() {
      @Override
      public void keyTyped(KeyEvent e) {
        if (e.getKeyChar() == KeyEvent.VK_ENTER) {
          String url = resourceField.getText();
          if (url == null || "".equals(url.trim())) {
            setImage(null);
          } else {
            ImageValue value = createNewOrCopy();
            try {
              if (!url.contains(":/")) {
                url = new File(url).toURI().toURL().toString();
{'fraction_non_alphanumeric': 0.10196022115315574, 'fraction_numerical': 0.004595390249156315, 'mean_word_length': 3.55461085676913, 'pattern_counts': {'":': 2, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4553652', 'n_tokens_mistral': 3882, 'n_tokens_neox': 3819, 'n_words': 1029}