/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* Part of the Processing project - http://processing.org Copyright (c) 2012-16 The Processing Foundation Copyright (c) 2004-12 Ben Fry and Casey Reas Copyright (c) 2001-04 Massachusetts Institute of Technology This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package processing.app.ui; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Image; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import javax.swing.plaf.basic.BasicSplitPaneDivider; import javax.swing.plaf.basic.BasicSplitPaneUI; import processing.app.Mode; import processing.app.Platform; import processing.core.PApplet; /** * Panel just below the editing area that contains status messages. */ public class EditorStatus extends BasicSplitPaneDivider { //JPanel { static final int HIGH = Toolkit.zoom(28); static final int LEFT_MARGIN = Editor.LEFT_GUTTER; static final int RIGHT_MARGIN = Toolkit.zoom(20); Color urlColor; Color[] fgColor; Color[] bgColor; Image[] bgImage; @SuppressWarnings("hiding") static public final int ERROR = 1; static public final int CURSOR_LINE_ERROR = 2; static public final int WARNING = 3; static public final int CURSOR_LINE_WARNING = 4; static public final int NOTICE = 0; static final int YES = 1; static final int NO = 2; static final int CANCEL = 3; static final int OK = 4; static final String NO_MESSAGE = ""; Editor editor; int mode; String message; String url; int rightEdge; int mouseX; boolean urlRollover; Font font; FontMetrics metrics; int ascent; Image offscreen; int sizeW, sizeH; int response; boolean indeterminate; Thread thread; public EditorStatus(BasicSplitPaneUI ui, Editor editor) { super(ui); this.editor = editor; empty(); updateMode(); addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { updateMouse(); } @Override public void mousePressed(MouseEvent e) { if (urlRollover) { Platform.openURL(url); } } @Override public void mouseExited(MouseEvent e) { updateMouse(); } }); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { mouseX = e.getX(); updateMouse(); } }); } void updateMouse() { if (urlRollover) { setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); } else { setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); } repaint(); } static String findURL(String message) { String[] m = PApplet.match(message, "http\\S+"); if (m != null) { return m[0]; } return null; } public void updateMode() { Mode mode = editor.getMode(); urlColor = mode.getColor("status.url.fgcolor"); fgColor = new Color[] { mode.getColor("status.notice.fgcolor"), mode.getColor("status.error.fgcolor"), mode.getColor("status.error.fgcolor"), mode.getColor("status.warning.fgcolor"), mode.getColor("status.warning.fgcolor") }; bgColor = new Color[] { mode.getColor("status.notice.bgcolor"), mode.getColor("status.error.bgcolor"), mode.getColor("status.error.bgcolor"), mode.getColor("status.warning.bgcolor"), mode.getColor("status.warning.bgcolor") }; bgImage = new Image[] { mode.loadImage("/lib/status/notice.png"), mode.loadImage("/lib/status/error.png"), mode.loadImage("/lib/status/error.png"), mode.loadImage("/lib/status/warning.png"), mode.loadImage("/lib/status/warning.png") }; font = mode.getFont("status.font"); metrics = null; } public void empty() { mode = NOTICE; message = NO_MESSAGE; url = null; repaint(); } public void message(String message, int mode) { this.message = message; this.mode = mode; url = findURL(message); repaint(); } public void notice(String message) { message(message, NOTICE); // mode = NOTICE; // this.message = message; // url = findURL(message); // repaint(); } // public void unnotice(String unmessage) { // if (message.equals(unmessage)) empty(); // } public void warning(String message) { message(message, WARNING); // this.message = message; // mode = WARNING; // url = findURL(message); // repaint(); } public void error(String message) { message(message, ERROR); // this.message = message; // mode = ERROR; // url = findURL(message); // repaint(); } public void startIndeterminate() { indeterminate = true; thread = new Thread() { public void run() { while (Thread.currentThread() == thread) { repaint(); try { Thread.sleep(1000 / 10); } catch (InterruptedException e) { } } } }; thread.setName("Editor Status"); thread.start(); } public void stopIndeterminate() { indeterminate = false; thread = null; repaint(); } //public void paintComponent(Graphics screen) { public void paint(Graphics screen) { // if (okButton == null) setup(); Dimension size = getSize(); if ((size.width != sizeW) || (size.height != sizeH)) { // component has been resized offscreen = null; } if (offscreen == null) { sizeW = size.width; sizeH = size.height; offscreen = Toolkit.offscreenGraphics(this, sizeW, sizeH); } Graphics g = offscreen.getGraphics(); /*Graphics2D g2 =*/ Toolkit.prepareGraphics(g); g.setFont(font); if (metrics == null) { metrics = g.getFontMetrics(); ascent = metrics.getAscent(); } g.drawImage(bgImage[mode], 0, 0, sizeW, sizeH, this); g.setColor(fgColor[mode]); // https://github.com/processing/processing/issues/3265 if (message != null) { // needs to be set each time on osx g.setFont(font); // calculate right edge of the text for rollovers (otherwise the pane // cannot be resized up or down whenever a URL is being displayed) rightEdge = LEFT_MARGIN + g.getFontMetrics().stringWidth(message); // set the highlight color on rollover so that the user's not surprised // to see the web browser open when they click urlRollover = (url != null) && (mouseX > LEFT_MARGIN && mouseX < rightEdge); if (urlRollover) { g.setColor(urlColor); } g.drawString(message, LEFT_MARGIN, (sizeH + ascent) / 2); } if (indeterminate) { //int x = cancelButton.getX(); //int w = cancelButton.getWidth(); int w = Toolkit.getButtonWidth(); int x = getWidth() - RIGHT_MARGIN - w; int y = getHeight() / 3; int h = getHeight() / 3; g.setColor(new Color(0x80000000, true)); g.drawRect(x, y, w, h); for (int i = 0; i < 10; i++) { int r = (int) (x + Math.random() * w); g.drawLine(r, y, r, y+h); } } screen.drawImage(offscreen, 0, 0, sizeW, sizeH, null); } public Dimension getPreferredSize() { return getMinimumSize(); } public Dimension getMinimumSize() { return new Dimension(Toolkit.zoom(300), HIGH); } public Dimension getMaximumSize() { return new Dimension(super.getMaximumSize().width, HIGH); } }