Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.awt.AWTException;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.Font;
- import java.awt.Graphics;
- import java.awt.Image;
- import java.awt.MenuItem;
- import java.awt.PopupMenu;
- import java.awt.SystemTray;
- import java.awt.Toolkit;
- import java.awt.TrayIcon;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.awt.event.MouseEvent;
- import java.awt.event.MouseListener;
- import java.io.File;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.PrintWriter;
- import java.text.DateFormat;
- import java.time.LocalDateTime;
- import java.util.ArrayList;
- import java.util.Date;
- import java.util.HashSet;
- import java.util.Locale;
- import java.util.Scanner;
- import java.util.logging.Level;
- import java.util.logging.Logger;
- import javax.imageio.ImageIO;
- import javax.swing.AbstractAction;
- import javax.swing.ActionMap;
- import javax.swing.InputMap;
- import javax.swing.JComponent;
- import javax.swing.JDialog;
- import javax.swing.JLabel;
- import javax.swing.JLayeredPane;
- import javax.swing.JOptionPane;
- import javax.swing.JTextArea;
- import javax.swing.KeyStroke;
- import org.jnativehook.GlobalScreen;
- import org.jnativehook.NativeHookException;
- import org.jnativehook.keyboard.NativeKeyEvent;
- import org.jnativehook.keyboard.NativeKeyListener;
- public class Main implements MouseListener, ActionListener, NativeKeyListener {
- final private int width = 400;
- final private int height = 400;
- private HashSet<Integer> pressedKeys = new HashSet<Integer>();
- private String answer = null;
- private JDialog frame;
- private ImagePanel imagePanel;
- private JLabel qLabel;
- private JTextArea aLabel;
- private String imgFilename;
- private String iconFilename;
- private ArrayList<Task> tasks;
- private ArrayList<String> notes;
- private PrintWriter log;
- private Color bg;
- private Color fg;
- private int pt;
- private int curTaskID;
- private void run(String[] args) throws InterruptedException {
- // Initialize stuff
- tasks = new ArrayList<Task>();
- notes = new ArrayList<String>();
- bg = new Color(0, 0, 0, 0);
- fg = new Color(255, 0, 0, 255);
- pt = 20;
- // Check if System Tray is supported
- if (!SystemTray.isSupported()) {
- System.err.println("System Tray is not supported");
- return;
- }
- // Parse the configuration file
- try {
- readConfig("./config");
- } catch (Exception e) {
- e.printStackTrace();
- System.err.println("\nCould not open config file:");
- System.err.println(e.getMessage());
- return;
- }
- // Read in the background image
- Image bgImage = null;
- try {
- bgImage = ImageIO.read(new File(imgFilename)).getScaledInstance(width, height, Image.SCALE_DEFAULT);
- } catch (IOException e) {
- e.printStackTrace();
- System.err.println("Could not read background image");
- return;
- }
- // Read in the background image
- Image iconImage = null;
- try {
- iconImage = ImageIO.read(new File(iconFilename));
- } catch (IOException e) {
- e.printStackTrace();
- System.err.println("Could not read icon image");
- return;
- }
- // Setup pop ups for system tray
- PopupMenu popup = new PopupMenu();
- MenuItem timeItem = new MenuItem(getTime(0));
- MenuItem refreshItem = new MenuItem("Refresh");
- MenuItem exitItem = new MenuItem("Exit");
- timeItem.setEnabled(false);
- refreshItem.addActionListener(this);
- exitItem.addActionListener(this);
- popup.add(timeItem);
- popup.add(refreshItem);
- popup.add(exitItem);
- popup.add(new MenuItem());
- // Setup system tray
- SystemTray tray = SystemTray.getSystemTray();
- TrayIcon trayIcon = new TrayIcon(iconImage);
- trayIcon.setImageAutoSize(true);
- trayIcon.setPopupMenu(popup);
- try {
- tray.add(trayIcon);
- } catch (AWTException e) {
- System.err.println("System tray icon could not be added");
- return;
- }
- // Initialize the JComponents
- imagePanel = new ImagePanel(bgImage);
- imagePanel.setSize(width, height);
- imagePanel.addMouseListener(this);
- qLabel = new JLabel();
- qLabel.setBackground(bg);
- qLabel.setForeground(fg);
- qLabel.setSize(width, height);
- aLabel = new JTextArea();
- aLabel.setLineWrap(true);
- InputMap input = aLabel.getInputMap();
- KeyStroke enter = KeyStroke.getKeyStroke("ENTER");
- KeyStroke shiftEnter = KeyStroke.getKeyStroke("shift ENTER");
- input.put(shiftEnter, "shift ENTER");
- input.put(enter, "ENTER");
- ActionMap actions = aLabel.getActionMap();
- actions.put("ENTER", new AbstractAction() {
- private static final long serialVersionUID = 2845098944540081988L;
- @Override
- public void actionPerformed(ActionEvent e) {
- answer = aLabel.getText();
- }
- });
- actions.put("shift ENTER", new AbstractAction() {
- private static final long serialVersionUID = -7395068805752131054L;
- @Override
- public void actionPerformed(ActionEvent e) {
- aLabel.setText(aLabel.getText() + "\n");
- }
- });
- // Get screen dimensions
- Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
- double W = screenSize.getWidth();
- double H = screenSize.getHeight();
- // Define the look of the frame
- frame = new JDialog();
- frame.setUndecorated(true);
- frame.setLocation((int) (W - width) / 2, (int) (H - height) / 2);
- frame.setBackground(new Color(0, 0, 0, 0));
- frame.setSize(width, height);
- frame.setAlwaysOnTop(true);
- frame.setVisible(false);
- // Continuously check for new tasks
- while (true) {
- // Get current time
- int curTime = LocalDateTime.now().getHour() * 60 + LocalDateTime.now().getMinute();
- // bestTime = max, now minimize bestTime
- int bestTime = curTime - 1;
- Task bestTask = null;
- // Check all valid tasks
- for (Task task : tasks) {
- // Check if it's tomorrow and task.start is better than
- // bestTime,
- // or if it's today and task.start is better than bestTime
- if ((bestTime < curTime && (curTime <= task.start || task.start <= bestTime))
- || (curTime < bestTime && curTime < task.start && task.start < bestTime)) {
- bestTime = task.start;
- bestTask = task;
- }
- if ((bestTime < curTime && (task.end >= curTime || task.end <= bestTime))
- || (curTime < bestTime && curTime < task.end && task.end < bestTime)) {
- bestTime = task.end;
- bestTask = task;
- }
- }
- // Note the time in the label
- timeItem.setLabel(getTime(bestTime));
- // Check every second to be precise
- while (curTime != bestTime) {
- if (toRefresh) {
- tray.remove(trayIcon);
- return;
- }
- Thread.sleep(500);
- curTime = LocalDateTime.now().getHour() * 60 + LocalDateTime.now().getMinute();
- }
- // Now process the task
- processTask(bestTask, bestTime == bestTask.end);
- // In order to update the time on the tray
- if (curTime == bestTime) {
- // Save values so we do not affect surrounding logic
- int oldCurTime = curTime;
- int oldBestTime = bestTime;
- // Get current time
- curTime++;
- // bestTime = max, now minimize bestTime
- bestTime = curTime - 1;
- bestTask = null;
- // Check all valid tasks
- for (Task task : tasks) {
- // Check if it's tomorrow and task.start is better than
- // bestTime,
- // or if it's today and task.start is better than bestTime
- if ((bestTime < curTime && (curTime <= task.start || task.start <= bestTime))
- || (curTime < bestTime && curTime < task.start && task.start < bestTime)) {
- bestTime = task.start;
- bestTask = task;
- }
- if ((bestTime < curTime && (task.end >= curTime || task.end <= bestTime))
- || (curTime < bestTime && curTime < task.end && task.end < bestTime)) {
- bestTime = task.end;
- bestTask = task;
- }
- }
- // Note the time in the label
- timeItem.setLabel(getTime(bestTime));
- // Restore these values
- curTime = oldCurTime;
- bestTime = oldBestTime;
- }
- // Wait until we move on
- while (curTime == bestTime) {
- if (toRefresh) {
- tray.remove(trayIcon);
- return;
- }
- Thread.sleep(500);
- curTime = LocalDateTime.now().getHour() * 60 + LocalDateTime.now().getMinute();
- }
- }
- }
- private void processTask(Task t, boolean end) throws InterruptedException {
- frame.getLayeredPane().removeAll();
- frame.getLayeredPane().add(qLabel);
- frame.getLayeredPane().add(aLabel);
- frame.getLayeredPane().add(imagePanel, JLayeredPane.DEFAULT_LAYER);
- for (Question q : t.questions) {
- if (end && q.pre || !end && !q.pre)
- continue;
- String text = q.text;
- /*
- * Calculate proper font size int pt = 0; FontMetrics fm; do { pt++;
- * Font font = new Font(qLabel.getFont().getName(), Font.PLAIN, pt);
- * fm = qLabel.getFontMetrics(font); fm.stringWidth(text); } while
- * (fm.stringWidth(text) < qLabel.getWidth()); pt--;
- */
- // qLabel.setSize(qLabel.getWidth(), fm.getHeight());
- // qLabel.setLocation(0, (height - fm.getHeight()) / 2);
- qLabel.setFont(new Font(qLabel.getFont().getName(), Font.PLAIN, pt));
- qLabel.setText("<html><center><p style=\"width:" + width + "\">" + text + "</p></center></html>");
- qLabel.setSize(qLabel.getPreferredSize());
- qLabel.setLocation(Math.max((width - qLabel.getWidth()) / 2, 0), (height - qLabel.getHeight()) / 2);
- qLabel.setOpaque(true);
- aLabel.setColumns(q.width);
- aLabel.setRows(q.height);
- aLabel.setSize(aLabel.getPreferredSize());
- aLabel.setSize(Math.min(aLabel.getWidth(), width), Math.min(aLabel.getHeight(), height));
- aLabel.setLocation((width - aLabel.getWidth()) / 2, qLabel.getLocation().y + qLabel.getHeight() + 10);
- aLabel.setText("");
- frame.setVisible(true);
- while (answer == null) {
- if (toRefresh) {
- return;
- }
- Thread.sleep(100);
- }
- q.ans = answer;
- answer = null;
- }
- frame.setVisible(false);
- if (end) {
- if (notes.size() > 0) {
- String ret = "";
- ret += "Notes: \n";
- for (String note : notes) {
- ret += note + "\n";
- }
- ret += "\n";
- JOptionPane.showMessageDialog(frame, ret);
- notes = new ArrayList<String>();
- }
- log.append(t.toString());
- log.flush();
- }
- }
- void readConfig(String filename) throws Exception {
- Scanner sc = new Scanner(new File(filename));
- String logFilename = null;
- int curLine = 0;
- Task t = null;
- try {
- while (sc.hasNextLine()) {
- curLine++;
- String sLine = sc.nextLine();
- if (!sLine.contains("=")) {
- t = null;
- continue;
- }
- String[] split = sLine.split("\\=");
- if (split.length != 2) {
- throw new Exception("There must only be a single equal sign per line");
- }
- String key = split[0];
- String val = split[1];
- switch (key) {
- case "png":
- imgFilename = val;
- break;
- case "icon":
- iconFilename = val;
- break;
- case "logfile":
- logFilename = val;
- log = new PrintWriter((new FileOutputStream(new File(val), true)));
- break;
- case "bg":
- String[] nums = val.split(",");
- if (nums.length < 3 || nums.length > 4) {
- throw new Exception("You must have 3 to 4 comma separated integers");
- }
- int r = Integer.parseInt(nums[0]);
- int g = Integer.parseInt(nums[1]);
- int b = Integer.parseInt(nums[2]);
- if (nums.length == 3)
- bg = new Color(r, g, b, 255);
- else
- bg = new Color(r, g, b, Integer.parseInt(nums[3]));
- break;
- case "fg":
- nums = val.split(",");
- if (nums.length < 3 || nums.length > 4) {
- throw new Exception("You must have 3 to 4 comma separated integers");
- }
- r = Integer.parseInt(nums[0]);
- g = Integer.parseInt(nums[1]);
- b = Integer.parseInt(nums[2]);
- if (nums.length == 3)
- fg = new Color(r, g, b, 255);
- else
- fg = new Color(r, g, b, Integer.parseInt(nums[3]));
- break;
- case "fontpt":
- pt = Integer.parseInt(val);
- break;
- case "start":
- t = new Task();
- String[] time = val.split(":");
- int hours = Integer.parseInt(time[0]);
- int minutes = Integer.parseInt(time[1]);
- t.start = hours * 60 + minutes;
- tasks.add(t);
- break;
- case "finish":
- if (t == null) {
- throw new Exception("\'finish\' was parsed before corresponding \'start\'");
- }
- time = val.split(":");
- hours = Integer.parseInt(time[0]);
- minutes = Integer.parseInt(time[1]);
- t.end = hours * 60 + minutes;
- break;
- default:
- String[] dim = key.split("x");
- if (dim.length != 2) {
- throw new Exception("Unknown key: " + key);
- }
- if (t == null) {
- throw new Exception("A question was parsed before a corresponding \'start\' was found.");
- }
- int w = Integer.parseInt(dim[0]);
- int h = Integer.parseInt(dim[1]);
- if (t.end == -1)
- t.addQuestion(val, w, h, true);
- else
- t.addQuestion(val, w, h, false);
- }
- }
- curLine = -1;
- curTaskID = 0;
- Scanner logFile = new Scanner(new File(logFilename));
- logFile.useDelimiter("\\Z");
- if( logFile.hasNext() )
- {
- String content = logFile.next();
- String[] lines = content.split("\n");
- for (int i = lines.length - 1; i >= 0; i--) {
- String line = lines[i];
- if (line.contains("Task")) {
- curTaskID = new Scanner(line.split("#")[1]).nextInt();
- break;
- }
- }
- }
- logFile.close();
- } catch (Exception e) {
- e.printStackTrace();
- if (curLine != -1)
- throw new Exception("Line: " + curLine + "\n" + e.getMessage(), e);
- else
- throw new Exception(e.getMessage(), e);
- } finally {
- if (sc != null)
- sc.close();
- }
- }
- class Question {
- public String ans;
- public String text;
- public int width;
- public int height;
- public boolean pre;
- Question(String text, int width, int height, boolean pre) {
- this.text = text;
- this.width = width;
- this.height = height;
- this.pre = pre;
- }
- }
- class Task {
- private int ID;
- public ArrayList<Question> questions = new ArrayList<Question>();
- public int start = -1;
- public int end = -1;
- public Task() {
- curTaskID++;
- ID = curTaskID;
- }
- void addQuestion(String q, int width, int height, boolean pre) {
- Question question = new Question(q, width, height, pre);
- questions.add(question);
- }
- public String toString() {
- String ret = "Task #" + ID + " ["
- + DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US).format(new Date()) + " " + getTime(start)
- + " - " + getTime(end) + "]\n\n";
- // if (notes != null && notes.size() > 0) {
- // ret += "Notes: \n";
- // for (String note : notes) {
- // ret += note + "\n";
- // }
- // ret += "\n";
- // }
- int qn = 0;
- for (Question q : questions) {
- qn++;
- ret += "Question #" + qn + "\n";
- ret += q.text + ": " + q.ans + "\n\n";
- }
- ret += "\n";
- return ret;
- }
- }
- class ImagePanel extends JComponent {
- private static final long serialVersionUID = 4522060807412287578L;
- private Image image;
- public ImagePanel(Image image) {
- this.image = image;
- }
- @Override
- protected void paintComponent(Graphics g) {
- super.paintComponent(g);
- g.drawImage(image, 0, 0, this);
- }
- }
- public static void main(String[] args) throws IOException {
- try {
- Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
- logger.setLevel(Level.OFF);
- GlobalScreen.registerNativeHook();
- } catch (NativeHookException e1) {
- e1.printStackTrace();
- return;
- }
- Main c = new Main();
- GlobalScreen.addNativeKeyListener(c);
- toRefresh = true;
- while (toRefresh) {
- toRefresh = false;
- try {
- c.run(args);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- System.exit(1);
- }
- int clicks = 0;
- @Override
- public void mouseClicked(MouseEvent arg0) {
- clicks++;
- if (clicks > 20) {
- }
- }
- @Override
- public void mouseEntered(MouseEvent arg0) {
- }
- @Override
- public void mouseExited(MouseEvent arg0) {
- }
- @Override
- public void mousePressed(MouseEvent arg0) {
- }
- @Override
- public void mouseReleased(MouseEvent arg0) {
- }
- static boolean toRefresh;
- @Override
- public void actionPerformed(ActionEvent ae) {
- switch (ae.getActionCommand()) {
- case "Exit":
- System.exit(0);
- break;
- case "Refresh":
- toRefresh = true;
- break;
- }
- }
- @Override
- public void nativeKeyPressed(NativeKeyEvent e) {
- pressedKeys.add(e.getKeyCode());
- }
- @Override
- public void nativeKeyReleased(NativeKeyEvent e) {
- pressedKeys.remove(e.getKeyCode());
- }
- @Override
- public void nativeKeyTyped(NativeKeyEvent e) {
- if (e.getKeyChar() == 'I' && (pressedKeys.contains(NativeKeyEvent.VC_CONTROL_L)
- || pressedKeys.contains(NativeKeyEvent.VC_CONTROL_R))) {
- String s = JOptionPane.showInputDialog(frame, null);
- // If a string was returned, save the note
- if ((s != null) && (s.length() > 0)) {
- notes.add(s);
- }
- }
- }
- String getTime(int time) {
- return ((time / 60) < 10 ? "0" : "") + (time / 60) + ":" + ((time % 60) < 10 ? "0" : "") + (time % 60);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement