) getValue("togglemenuList");
+ if (jmial != null) for(JCheckBoxMenuItem jmi0: jmial) if(jmi0!=null) jmi0.setSelected(isSelected);
+ }
+ /**
+ * 未使用
+ * @param e
+ */
+ public void itemStateChanged(ItemEvent e){
+ for(ItemListener il: itemListenerAry){
+ il.itemStateChanged(e);
+ }
+ }
+ public boolean isSelected() {
+ return isSelected;
+ }
+
+ public void doClick() {
+ actionPerformed(new ActionEvent(this, 1, "doClick"));
+ }
+
+}
diff --git a/src/main/java/info/istlab/Zemi01/imgview/MyPCanvas.java b/src/main/java/info/istlab/Zemi01/imgview/MyPCanvas.java
new file mode 100644
index 0000000..5271b51
--- /dev/null
+++ b/src/main/java/info/istlab/Zemi01/imgview/MyPCanvas.java
@@ -0,0 +1,207 @@
+package info.istlab.Zemi01.imgview;
+
+import java.awt.AWTException;
+import java.awt.Point;
+import java.awt.Robot;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+import java.awt.geom.Point2D;
+
+import org.piccolo2d.PCamera;
+import org.piccolo2d.PCanvas;
+import org.piccolo2d.PInputManager;
+import org.piccolo2d.event.PBasicInputEventHandler;
+import org.piccolo2d.event.PInputEvent;
+import org.piccolo2d.event.PInputEventFilter;
+import org.piccolo2d.event.PPanEventHandler;
+import org.piccolo2d.extras.event.PSelectionEventHandler;
+import org.piccolo2d.extras.event.PZoomToEventHandler;
+import org.piccolo2d.util.PBounds;
+
+@SuppressWarnings("serial")
+
+
+
+public class MyPCanvas extends PCanvas {
+
+ static PInputEventFilter b1mask = new PInputEventFilter(
+ InputEvent.BUTTON1_MASK);
+
+ static PInputEventFilter b2mask = new PInputEventFilter(
+ InputEvent.BUTTON2_MASK);
+
+ static PInputEventFilter b3mask = new PInputEventFilter(
+ InputEvent.BUTTON3_MASK);
+
+ static PInputEventFilter disablemask = new PInputEventFilter(0);
+
+ PBasicInputEventHandler flowmenuEventHandler;
+
+ PSelectionEventHandler selectionEventHandler;
+
+ PPanEventHandler panEventHandler;
+
+ PZoomToEventHandler zoomeh;
+
+ Point2D cursorpoint;
+
+ public PCamera cam;
+
+ WheelZoomEventHandler wheelzoom;
+
+ public MouseWheelRotationListener wheelListener;
+
+ /**
+ * ホイール回転時のズーム方向.1または-1.デフォルトは1 = 手前(下)回転でズームイン
+ */
+// public int wheelrotationdirection = -1;
+
+ /**
+ * カーソルを中央にもってくるかどうか
+ */
+ public boolean moveMouseCursorOnZoomIn = true;
+ Robot robot;
+
+ /**
+ * ズーム時の幅
+ */
+ public float wheelZoomRatio = 1.0f;
+
+ public MyPCanvas() {
+ super();
+ initialize();
+ try {
+ robot = new Robot();
+ } catch (AWTException e) {
+ }
+ }
+ /**
+ * 擬似的なクリック
+ * @param x
+ * @param y
+ */
+ public void pseudoClick(int x, int y){
+ getRoot().getDefaultInputManager().processEventFromCamera(new MouseEvent(this,0,0,MouseEvent.BUTTON1,x,y,1,true), MouseEvent.MOUSE_PRESSED, getCamera());
+ getRoot().getDefaultInputManager().processEventFromCamera(new MouseEvent(this,0,0,MouseEvent.BUTTON1,x,y,1,false), MouseEvent.MOUSE_RELEASED, getCamera());
+ }
+
+ public void setWheelRotationDirection(int d){
+ if (wheelzoom != null) wheelzoom.setDirection(d);
+ }
+ public void setMouseWheelRotationListener(MouseWheelRotationListener l){
+ wheelListener = l;
+ }
+ public void setWheelZoomRatio(float f){
+ wheelZoomRatio = f;
+ }
+
+ public PBasicInputEventHandler getWheelListener() {
+ return wheelzoom;
+ }
+
+ class WheelZoomEventHandler extends PBasicInputEventHandler {
+ public int direction = -1;
+ public void setDirection(int d){
+ direction = d;
+ }
+ public void mouseWheelRotated(PInputEvent e) {
+ if (!e.isControlDown() && !e.isShiftDown() && !e.isAltDown()) {
+ PCamera pc = getCamera();
+
+// System.out.println("wheel rotation: " + pc.getAttribute("hoge"));
+ PBounds pb = pc.getViewBounds();
+// System.out.println(pb.toString());
+ float f = 1.0f + (0.1f * direction * e.getWheelRotation());
+ if (e.getWheelRotation() //下に回すと正になるので
+ * direction < 0) {
+ pb = zoomBounds_focusbyCursor(pb, f);
+ } else {
+ pb = BUtil.zoomBounds(pb, f);
+ }
+ if (pb.x == 0 && pb.y == 0) {
+ System.out.println("ズームイン位置がまだ準備前");
+ return;
+ }
+ pc.animateViewToCenterBounds(pb, true, 0);
+ if (MyPCanvas.this.wheelListener != null) MyPCanvas.this.wheelListener.mouseWheelRotated(f);
+ }
+ }
+ }
+
+ public void initialize() {
+ cam = getCamera();
+
+ disablemask.rejectAllEventTypes();
+
+ wheelzoom = new WheelZoomEventHandler();
+ wheelzoom.setEventFilter(b2mask);
+ cam.addInputEventListener(wheelzoom);
+
+ // panEventHandler = new PPanEventHandler();
+ // getPanEventHandler().setEventFilter(disablemask);
+ // panEventHandler.setEventFilter(b2mask);
+ // addInputEventListener(panEventHandler);
+ getPanEventHandler().setEventFilter(b2mask);
+ // check current cursor position
+ addInputEventListener(new PInputManager() {
+ public void mouseMoved(PInputEvent e) {
+ cursorpoint = e.getCanvasPosition();
+ try {
+ e.getPath().getPathTransformTo(getLayer()).inverseTransform(cursorpoint, cursorpoint);
+ } catch (RuntimeException ex) {
+ cursorpoint = e.getPosition(); // Camera付きのメニューボタンや,背景部分(PCamera)のとき
+ }
+ // TODO: 本来であればRuntimeExceptionを出さずに処理したいのだが..
+// e.getPickedNode().localToParent(cursorpoint);
+// System.out.println(e.getPickedNode().getRoot().getClass().getName());
+// if (e.getPickedNode() instanceof PCamera)
+// else cursorpoint = e.getPositionRelativeTo(getLayer());
+// catch (NoninvertibleTransformException e1) {
+// // TODO Auto-generated catch block
+// e1.printStackTrace();
+// }
+ }
+ });
+ }
+
+ public PBounds zoomBounds_focusbyCursor(PBounds pb, double rate) {
+ double x = pb.getX();
+ double y = pb.getY();
+ double w = pb.getWidth();
+ double h = pb.getHeight();
+ double nw = w * rate;
+ double nh = h * rate;
+ Point2D camcp = cam.getViewBounds().getCenter2D();
+ double camcx = camcp.getX();
+ double camcy = camcp.getY();
+// System.out.println("camcp "+camcx+" "+camcy);
+ double curx = cursorpoint.getX();
+ double cury = cursorpoint.getY();
+// System.out.println("cursor "+curx+" "+cury);
+ double nx = x - (nw - w) / 2 + curx - camcx;
+ double ny = y - (nh - h) / 2 + cury - camcy;
+ PBounds ret = new PBounds(nx, ny, nw, nh);
+ cursorpoint = ret.getCenter2D();
+ if (moveMouseCursorOnZoomIn) {
+ moveCursorPointCenter();
+ } else {
+ }
+ return ret;
+ }
+
+ public void moveCursorPointCenter() {
+ Point canvasglobalp = getLocationOnScreen();
+ int canvasw = getWidth();
+ int canvash = getHeight();
+ if (robot != null)
+ robot.mouseMove((int) (canvasglobalp.getX() + canvasw / 2),
+ (int) (canvasglobalp.getY() + canvash / 2));
+ }
+}
+
+//@SuppressWarnings("serial")
+//class MyPCanvas_noPointerZoom extends MyPCanvas {
+//public PBounds zoomBounds_focusbyCursor(PBounds pb, double rate) {
+//return BUtil.zoomBounds(pb, rate);
+//}
+//}
diff --git a/src/main/java/info/istlab/Zemi01/imgview/MyPImage.java b/src/main/java/info/istlab/Zemi01/imgview/MyPImage.java
new file mode 100644
index 0000000..818f85c
--- /dev/null
+++ b/src/main/java/info/istlab/Zemi01/imgview/MyPImage.java
@@ -0,0 +1,339 @@
+package info.istlab.Zemi01.imgview;
+
+/*
+ * Copyright (c) 2002-@year@, University of Maryland
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this list of conditions
+ * and the following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
+ * and the following disclaimer in the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of the University of Maryland nor the names of its contributors may be used to
+ * endorse or promote products derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Piccolo was written at the Human-Computer Interaction Laboratory www.cs.umd.edu/hcil by Jesse Grosjean
+ * under the supervision of Ben Bederson. The Piccolo website is www.cs.umd.edu/hcil/piccolo.
+ */
+
+import java.awt.Graphics2D;
+import java.awt.GraphicsConfiguration;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.MediaTracker;
+import java.awt.Toolkit;
+import java.awt.image.BufferedImage;
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
+
+import org.piccolo2d.PNode;
+import org.piccolo2d.util.PBounds;
+import org.piccolo2d.util.PPaintContext;
+
+/**
+ * PImage is a wrapper around a java.awt.Image. If this node is copied or
+ * serialized that image will be converted into a BufferedImage if it is not
+ * already one.
+ *
+ *
+ * 上記のやり方だと,一度シリアライズした画像データは非常にかさばる形式になり,
+ * 保存にむいていない.また,レンダリングにも時間がかかる.
+ * そのため,元画像のソース(JPGならJPGファイル,GIFならGIFファイル)のバイナリを
+ * 保存しておき,デシリアライズ時に回復するクラスをつくり,MyPImageとして用意した.
+ *
+ * @version 1.0
+ * @author Jesse Grosjean
+ */
+public class MyPImage extends PNode {
+
+ private static final long serialVersionUID = -2779887448253879707L;
+ /**
+ * The property name that identifies a change of this node's image (see
+ * {@link #getImage getImage}). Both old and new value will be set correctly
+ * to Image objects in any property change event.
+ */
+ public static final String PROPERTY_IMAGE = "image";
+ public static final int PROPERTY_CODE_IMAGE = 1 << 15;
+
+ private transient Image image;
+ public byte[] sourcebytes; // ここに,イメージの基を溜め込む
+
+ public MyPImage() {
+ super();
+ }
+
+ /**
+ * Construct a new PImage wrapping the given java.awt.Image.
+ */
+ public MyPImage(Image newImage) {
+ this();
+ sourcebytes = getImageBytesFromImage(newImage);
+ restoreImage();
+// setImage(newImage);
+ }
+
+ public MyPImage(Image newImage, String jpgORpng) {
+ this();
+ sourcebytes = getImageBytesFromImage(newImage, jpgORpng);
+ restoreImage();
+ }
+ public MyPImage(byte[] bytes, boolean copy){
+ if (copy) {
+ sourcebytes = new byte[bytes.length];
+ for(int i=0;inull, create an
+ * empty PImage; this behaviour is useful when fetching resources that may
+ * be missing.
+ */
+ public MyPImage(java.net.URL url) {
+ this();
+ if (url != null) setImage(Toolkit.getDefaultToolkit().getImage(url));
+ }
+
+ /**
+ * Returns the image that is shown by this node.
+ * @return the image that is shown by this node
+ */
+ public Image getImage() {
+ return image;
+ }
+
+ /**
+ * Set the image that is wrapped by this PImage node. This method will also
+ * load the image using a MediaTracker before returning.
+ */
+ public void restoreImage() {
+ image = Toolkit.getDefaultToolkit().createImage(sourcebytes);
+ setImage(image);
+// setImage(Toolkit.getDefaultToolkit().getImage(fileName));
+ }
+
+ public void readImageToBuffer(String s){
+ File f = new File(s);
+ long fsize = f.length();
+
+ InputStream in = null;
+ int b;
+ try {
+ in = new BufferedInputStream(new FileInputStream(s));
+ final int LS = 1024;
+ byte buf[] = new byte[LS];
+ ByteArrayOutputStream varyBuf = new ByteArrayOutputStream((int)fsize) ;
+
+ while((b = in.read(buf, 0, buf.length)) != -1 ) {
+ varyBuf.write(buf,0,b) ;
+ }
+ sourcebytes = varyBuf.toByteArray();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ }
+ }
+
+
+
+ /**
+ * Set the image that is wrapped by this PImage node. This method will also
+ * load the image using a MediaTracker before returning.
+ */
+ public void setImage(Image newImage) {
+ Image old = image;
+
+ if (newImage instanceof BufferedImage) {
+ image = newImage;
+ } else { // else make sure the image is loaded
+// 画像の読込完了を待つ
+ MediaTracker mt = new MediaTracker(new JFrame());
+ mt.addImage(newImage, 0);
+ try{
+ mt.waitForID(0);
+ }catch(InterruptedException e){}
+ image = newImage;
+ }
+ if (image != null) {
+ setBounds(0, 0, getImage().getWidth(null), getImage().getHeight(null));
+ invalidatePaint();
+ } else {
+ image = null;
+ }
+
+ firePropertyChange(PROPERTY_CODE_IMAGE, PROPERTY_IMAGE, old, image);
+ }
+
+ protected void paint(PPaintContext paintContext) {
+ if (getImage() != null) {
+ double iw = image.getWidth(null);
+ double ih = image.getHeight(null);
+ PBounds b = getBoundsReference();
+ Graphics2D g2 = paintContext.getGraphics();
+
+ if (b.x != 0 || b.y != 0 || b.width != iw || b.height != ih) {
+ g2.translate(b.x, b.y);
+ g2.scale(b.width / iw, b.height / ih);
+ g2.drawImage(image, 0, 0, null);
+ g2.scale(iw / b.width, ih / b.height);
+ g2.translate(-b.x, -b.y);
+ } else {
+ g2.drawImage(image, 0, 0, null);
+ }
+ }
+ }
+
+ //****************************************************************
+ // Serialization
+ //****************************************************************
+
+ /**
+ * The java.awt.Image wrapped by this PImage is converted into a BufferedImage
+ * when serialized.
+ */
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+// BufferedImage bufferedImage = toBufferedImage(image, false);
+// if (bufferedImage != null) ImageIO.write(bufferedImage, "png", out);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ image = Toolkit.getDefaultToolkit().createImage(sourcebytes);
+ // 画像の読込完了を待つ
+ MediaTracker mt = new MediaTracker(new JFrame());
+ mt.addImage(image, 0);
+ try{
+ mt.waitForID(0);
+ }catch(InterruptedException e){}
+// invalidatePaint();
+// image = ImageIO.read(in);
+ }
+
+ //****************************************************************
+ // Util
+ //****************************************************************
+
+ /**
+ * If alwaysCreateCopy is false then if the image is already a buffered
+ * image it will not be copied and instead the original image will just be
+ * returned.
+ */
+ public static BufferedImage toBufferedImage(Image image, boolean alwaysCreateCopy) {
+ if (image == null) return null;
+
+ if (!alwaysCreateCopy && image instanceof BufferedImage) {
+ return (BufferedImage) image;
+ } else {
+ GraphicsConfiguration graphicsConfiguration = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
+ BufferedImage result = graphicsConfiguration.createCompatibleImage(image.getWidth(null), image.getHeight(null));
+ Graphics2D g2 = result.createGraphics();
+ g2.drawImage(image, 0, 0, null);
+ g2.dispose();
+ return result;
+ }
+ }
+ public BufferedImage getBufferedImage(){
+ return toBufferedImage(image, true);
+ }
+
+ /**
+ * イメージを変換し,取り込み
+ * @param img
+ * @param format "jpg"or"png";
+ */
+ public static byte[] getImageBytesFromImage(Image img, String format){
+ ByteArrayOutputStream buf = new ByteArrayOutputStream();
+ try {
+ ImageIO.write(toBufferedImage(img, true), format, buf);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return buf.toByteArray();
+ }
+
+ public static byte[] getImageBytesFromImage(Image img){
+ byte[] png = getImageBytesFromImage(img, "png");
+ byte[] jpg = getImageBytesFromImage(img, "jpg");
+// System.out.println("png "+png.length + " jpg "+jpg.length);
+ if (png.length <= jpg.length) {
+// System.out.println("png is better ");
+ return png;
+ } else {
+// System.out.println("jpg is better ");
+ return jpg;
+ }
+
+ }
+
+ //****************************************************************
+ // Debugging - methods for debugging
+ //****************************************************************
+
+ /**
+ * Returns a string representing the state of this node. This method is
+ * intended to be used only for debugging purposes, and the content and
+ * format of the returned string may vary between implementations. The
+ * returned string may be empty but may not be null
.
+ *
+ * @return a string representation of this node's state
+ */
+ protected String paramString() {
+ StringBuffer result = new StringBuffer();
+
+ result.append("image=" + (image == null ? "null" : image.toString()));
+ result.append(',');
+ // result.append(super.paramString()); //APIが古くてなくなったので、とりあえず削除した。
+
+ return result.toString();
+ }
+
+ public MyPImage localClone(){
+ MyPImage clone = (MyPImage) this.clone();
+ clone.setImage(this.getImage());
+ clone.setBounds(this.getBounds());
+ clone.removeAllChildren();
+ return clone;
+ }
+}
diff --git a/src/main/java/info/istlab/Zemi01/imgview/PPPath.java b/src/main/java/info/istlab/Zemi01/imgview/PPPath.java
new file mode 100644
index 0000000..641934a
--- /dev/null
+++ b/src/main/java/info/istlab/Zemi01/imgview/PPPath.java
@@ -0,0 +1,64 @@
+package info.istlab.Zemi01.imgview;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Shape;
+import java.awt.Stroke;
+import java.awt.geom.Ellipse2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.Rectangle2D;
+
+import org.piccolo2d.nodes.PPath;
+
+/**
+ * 以前のPiccolo PPathとの互換性をとるためのクラス
+ */
+public class PPPath extends PPath.Double {
+ private static final Rectangle2D.Float TEMP_RECTANGLE = new Rectangle2D.Float();
+ private static final Ellipse2D.Float TEMP_ELLIPSE = new Ellipse2D.Float();
+ private static final BasicStroke DEFAULT_STROKE = new BasicStroke(1.0f);
+ private static final Color DEFAULT_STROKE_PAINT = Color.black;
+ private transient Stroke stroke;
+ public PPPath(){
+ super(new Path2D.Float());
+ // setStrokePaint(DEFAULT_STROKE_PAINT);
+ // setStroke(DEFAULT_STROKE);
+ setPaint(null);
+ }
+ public PPPath(Shape aShape) {
+ this(aShape, DEFAULT_STROKE);
+ }
+ public PPPath(Shape aShape, Stroke aStroke) {
+ this();
+ stroke = aStroke;
+ if (aShape != null) append(aShape, false);
+ }
+ public void setPathTo(final Shape aShape) {
+ this.getPathReference().reset();
+ append(aShape, false);
+ }
+ public void setPathToRectangle(float x, float y, float width, float height){
+ TEMP_RECTANGLE.setFrame(x, y, width, height);
+ setPathTo(TEMP_RECTANGLE);
+ }
+ public void setPathToEllipse(float x, float y, float width, float height) {
+ TEMP_ELLIPSE.setFrame(x, y, width, height);
+ setPathTo(TEMP_ELLIPSE);
+ }
+ /**
+ * Return a reference to the list used to manage this node's
+ * children. This list should not be modified.
+ *
+ * @return reference to the children list
+ */
+ // public List getChildrenReference() {
+ // if (children == null) {
+ // children = new ArrayList();
+ // }
+ // return children;
+ // }
+ // public PInterpolatingActivity animateToStrokeColor(final Color destColor, final long duration) {
+ // return super.animateToColor(destColor, duration);
+
+ // }
+}
diff --git a/src/main/java/info/istlab/Zemi01/imgview/QuickMenuActionManager.java b/src/main/java/info/istlab/Zemi01/imgview/QuickMenuActionManager.java
new file mode 100644
index 0000000..a452e46
--- /dev/null
+++ b/src/main/java/info/istlab/Zemi01/imgview/QuickMenuActionManager.java
@@ -0,0 +1,149 @@
+package info.istlab.Zemi01.imgview;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemListener;
+import java.awt.event.KeyListener;
+import java.util.ArrayList;
+import java.util.Hashtable;
+
+import javax.swing.AbstractButton;
+import javax.swing.Action;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JToggleButton;
+import javax.swing.JToolBar;
+
+public class QuickMenuActionManager {
+ protected KeepOrderHash> menurepos; // "File"=> ArrayList
+ protected Hashtable name2act;
+ protected Hashtable name2tbutton;
+ public QuickMenuActionManager(){
+ menurepos = new KeepOrderHash>();
+ name2act = new Hashtable();
+ name2tbutton = new Hashtable();
+ }
+ protected MyAction lastOne;
+ public void addAction(String type, MyAction a){
+ ArrayList al = menurepos.get(type);
+ if (al == null){
+ al = new ArrayList();
+ al.add(a);
+ menurepos.put(type, al);
+ } else {
+ al.add(a);
+ }
+ name2act.put((String)a.getValue(Action.NAME), a);
+ System.out.println((String)a.getValue(Action.NAME));
+ lastOne = a;
+ }
+ public void addHandler_Action(ActionListener al){
+ lastOne.addActionListenerToAry(al);
+ }
+ public void addHandler_Item(ItemListener il){
+ lastOne.addItemListenerToAry(il);
+ }
+ public MyAction getAction(String key){
+ return name2act.get(key);
+ }
+ public AbstractButton getButton(String key){
+ return name2tbutton.get(key);
+ }
+
+ public JMenuBar getMenuBar(){
+ JMenuItem menuItem = null;
+ JMenuBar menuBar;
+
+ //Create the menu bar.
+ menuBar = new JMenuBar();
+
+ for(String type: menurepos.getIterator()){
+ JMenu mainMenu = new JMenu(type);
+ for(Action a: menurepos.get(type)){
+ if (a.getValue("toggle") != null){
+ menuItem = new JCheckBoxMenuItem(a);
+ a.putValue("togglemenu", menuItem);
+ } else {
+ menuItem = new JMenuItem(a);
+ }
+// menuItem.setIcon(null); //arbitrarily chose not to use icon
+ mainMenu.add(menuItem);
+ }
+ menuBar.add(mainMenu);
+ }
+ return menuBar;
+ }
+ public JToolBar getToolBar(KeyListener editor) {
+ AbstractButton button = null;
+
+ //Create the toolbar.
+ JToolBar toolBar = new JToolBar();
+
+ for(String type: menurepos.getIterator()){
+ for(Action a: menurepos.get(type)){
+ if (a.getValue("toggle") != null){
+ button = new JToggleButton(a);
+ a.putValue("togglebutton", button);
+ } else {
+ button = new JButton(a);
+ }
+ if (button.getIcon() != null) {
+// button.setText(""); //an icon-only button
+ }
+ toolBar.add(button);
+ button.addKeyListener(editor);
+ name2tbutton.put(button.getText(),button);//あとでテキスト隠したりするときに参照が必要なので
+// System.out.println("BUTTON:: "+button.getText());
+ }
+ toolBar.addSeparator();
+ }
+ return toolBar;
+ }
+
+ /** Returns an ImageIcon, or null if the path was invalid. */
+ public static ImageIcon createNavigationIcon(String imageName) {
+ ClassLoader cl = QuickMenuActionManager.class.getClassLoader();
+
+ if (cl == null) {
+ System.err.println("Resource not found: "+ imageName);
+ return null;
+ }
+ String imgLocation = "toolbarButtonGraphics/"
+ + imageName
+ + ".gif";
+ if (imageName.startsWith("_")){
+ imgLocation = "myicon/" + imageName.substring(1)+".gif";
+ ImageIcon ii;
+ try{
+ ii = new ImageIcon(cl.getResource(imgLocation));
+ }catch(NullPointerException ex){
+ ii = new ImageIcon("resource/"+imgLocation);
+ }
+ return ii;
+ } else {
+
+// java.net.URL imageURL = maincls.getResource(imgLocation);
+
+ return new ImageIcon(cl.getResource(imgLocation));
+ }
+ }
+ public void foldToolbarText(boolean f){
+ if (f){
+ for(AbstractButton ab: name2tbutton.values()){
+ if (ab.getIcon()!= null){
+ ab.setText(null);
+ }
+ }
+ } else {
+ for(String key: name2tbutton.keySet()){
+ AbstractButton ab = name2tbutton.get(key);
+ ab.setText(key);
+// ab.validate();
+ }
+ }
+ }
+
+}
+
diff --git a/src/main/java/info/istlab/Zemi01/imgview/ScrCapture.java b/src/main/java/info/istlab/Zemi01/imgview/ScrCapture.java
new file mode 100644
index 0000000..8637267
--- /dev/null
+++ b/src/main/java/info/istlab/Zemi01/imgview/ScrCapture.java
@@ -0,0 +1,469 @@
+package info.istlab.Zemi01.imgview;
+
+import java.awt.AWTException;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.awt.Robot;
+import java.awt.Toolkit;
+import java.awt.image.AreaAveragingScaleFilter;
+import java.awt.image.BufferedImage;
+import java.awt.image.ConvolveOp;
+import java.awt.image.FilteredImageSource;
+import java.awt.image.ImageFilter;
+import java.awt.image.ImageProducer;
+import java.awt.image.Kernel;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.imageio.ImageIO;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+
+//import com.sun.image.codec.jpeg.JPEGCodec;
+//import com.sun.image.codec.jpeg.JPEGEncodeParam;
+//import com.sun.image.codec.jpeg.JPEGImageEncoder;
+
+
+public class ScrCapture implements Runnable {
+ public Thread capthread;
+
+ public String format;
+ public int msec;
+ public CaptureCallback retobj;
+ byte[] bb;
+ int mochatstate = -1;
+ int limitsize = 0;
+ JFrame parentFrame;
+
+ public ScrCapture(String format, CaptureCallback call, int wait_msec, JFrame parent){
+ retobj = call;
+ this.format = format;
+ msec = wait_msec;
+ parentFrame = parent;
+
+ capthread = new Thread(this);
+ capthread.start();
+
+ }
+
+ @Override
+ public void run() {
+ if (parentFrame != null) parentFrame.setState(JFrame.ICONIFIED);
+ try {
+ Thread.sleep(msec); // プラス2秒は,captureのなかで
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ capture();
+
+ }
+ public void capture(){
+ System.out.print("capture - ");
+ String osname = InfoGetter.getOsNameString();
+ if (osname.startsWith("Linux")){
+ // bb = getImageFromClipboard("JPG");
+ bb = getImageFromGnome(format); //JPG or PNG
+ } else {
+ bb = getImage(format); //JPG or PNG
+ }
+ // if (bb == null) return;//キャプチャエラーか,60秒以内に操作しなかった.
+ System.out.println(format+":"+bb.length);
+ retobj.finished(bb);
+
+ if (parentFrame != null) parentFrame.setState(JFrame.NORMAL);
+ }
+ public byte[] getImage(String imgtype){
+ // capture the whole screen
+ BufferedImage screencapture = null;
+ try {
+ screencapture = new Robot().createScreenCapture(
+ new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
+ } catch (AWTException e1) {
+ e1.printStackTrace();
+ }
+
+ ByteArrayOutputStream imgbaos = new ByteArrayOutputStream();
+ try{
+ ImageIO.write(screencapture, imgtype, imgbaos);
+ } catch(IOException ex){
+ System.out.println("can't capture");
+ }
+ if (imgtype == "JPG"){
+ // byte[] b = miniImage(imgbaos.toByteArray(), imgbaos.size()*2/3);
+ byte[] b = miniImage(imgbaos.toByteArray(), 1024*60);
+ return b;
+ }
+ return imgbaos.toByteArray();
+
+ // Save as JPEG
+ // File file = new File("screencapture.png");
+ // try {
+ // ImageIO.write(screencapture, "png", file);
+ // } catch (IOException e) {
+ // e.printStackTrace();
+ // }
+ }
+
+ Process process = null;
+ public byte[] getImageFromGnome(String imgtype){
+ //この時刻よりも後のファイルだけを対象とする
+ SimpleDateFormat sdf;
+// sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
+ sdf = new SimpleDateFormat("yyyy-MM-dd hh-mm-ss");
+ String compareFileName = "Screenshot from "+sdf.format(new Date())+".png";
+ try { Thread.sleep(2000); } catch (InterruptedException e1) { e1.printStackTrace(); }
+ String command;
+ command = "/usr/bin/gnome-screenshot";
+ // command = "/usr/bin/gsettings set org.gnome.gnome-screenshot auto-save-directory file:///home/t/"+ig.uid;
+ try {
+ process = Runtime.getRuntime().exec(command);
+ } catch (IOException e1) { e1.printStackTrace(); }
+ command = "/usr/bin/gnome-screenshot";
+ try {
+ process = Runtime.getRuntime().exec(command);
+ } catch (IOException e1) { e1.printStackTrace(); }
+ //wait and load
+ int count=32;
+ File toberemoved = null;
+ while(count>0 && toberemoved ==null){
+ try { Thread.sleep(2000); } catch (InterruptedException e1) { e1.printStackTrace(); }
+ File f = new File("capture.png");
+ for(File ff: f.listFiles()){
+ String target = ff.getName();
+ System.out.println("checking "+ff.getAbsoluteFile());
+ if (target.startsWith("Screenshot from 20")){
+ if (target.compareTo(compareFileName) > 0){
+ toberemoved = ff;
+ break;
+ }
+ }
+ }
+ count--;
+ }
+ if (toberemoved == null) {
+ JOptionPane.showMessageDialog(null, "画面レポート送信失敗.\n\nキャプチャ後,60秒以内に「保存(S)」をおしてください.\n\n保存をキャンセルして,もう一度Shussekiのメニューから「送信>画面レポート」を実行してください.");
+ return null;
+ }
+ BufferedImage screencapture = null;
+ try {
+ screencapture = ImageIO.read(toberemoved);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ ByteArrayOutputStream imgbaos = new ByteArrayOutputStream();
+ try{
+ ImageIO.write(screencapture, imgtype, imgbaos);
+ } catch(IOException ex){
+ System.out.println("can't capture");
+ }
+ try {
+ imgbaos.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ toberemoved.delete();
+ if (imgtype == "JPG" && limitsize > 0){
+ // byte[] b = miniImage(imgbaos.toByteArray(), imgbaos.size()*2/3);
+ byte[] b = miniImage(imgbaos.toByteArray(), limitsize);
+ return b;
+ }
+ return imgbaos.toByteArray();
+ }
+
+ /**
+ * サイズの圧縮
+ * @param byteData
+ * @param max_bytesize
+ * @return
+ */
+ byte[] miniImage(byte[] byteData, double max_bytesize) {
+ if (byteData == null)
+ return null;
+
+ ByteArrayInputStream input = new ByteArrayInputStream(byteData);
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try {
+ BufferedImage image = ImageIO.read(input);
+ ImageIO.write(image,"jpeg",output);
+// JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(output);
+//
+// JPEGEncodeParam encodeParam = encoder
+// .getDefaultJPEGEncodeParam(image);
+
+ // boolean widthCheck = false;
+ // boolean heightCheck = false;
+ //
+ // JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(input);
+
+// float sizeValue = new Float(max_bytesize).floatValue()
+// / byteData.length;
+
+// encodeParam.setQuality(sizeValue, false);
+// encoder.encode(image, encodeParam);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ input.close();
+ output.flush();
+ output.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ byte[] byteDataResult = null;
+ if (output.size() > 0)
+ byteDataResult = output.toByteArray();
+
+ return byteDataResult;
+ }
+ public BufferedImage toBufferedImage(Image img){
+ if (img instanceof BufferedImage)
+ {
+ return (BufferedImage) img;
+ }
+
+ // Create a buffered image with transparency
+ BufferedImage bimage = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
+
+ // Draw the image on to the buffered image
+ Graphics2D bGr = bimage.createGraphics();
+ bGr.drawImage(img, 0, 0, null);
+ bGr.dispose();
+
+ // Return the buffered image
+ return bimage;
+ }
+
+ public static void writeBytesToFile(String filepath, byte[] ba){
+ OutputStream fos = null;
+ DataOutputStream dos = null;
+ try{
+ fos = new FileOutputStream(filepath);
+ dos = new DataOutputStream(fos);
+ dos.write(ba);
+ dos.close();
+ fos.close();
+ }catch(IOException iex){
+ iex.printStackTrace(System.out);
+ }
+ }
+
+ public static byte[] readBytesFromFile(String filepath){
+ InputStream fos = null;
+ DataInputStream dos = null;
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ try{
+ fos = new FileInputStream(filepath);
+ dos = new DataInputStream(fos);
+ int len;
+ byte buf[] = new byte[1024];
+ while((len=dos.read(buf))!=-1){
+ output.write(buf, 0, len);
+ }
+ dos.close();
+ fos.close();
+ }catch(IOException iex){
+ iex.printStackTrace(System.out);
+ }
+ return output.toByteArray();
+ }
+
+ public static ByteArrayOutputStream crop(ByteArrayInputStream input, String format, int[] rect){
+ ByteArrayOutputStream imgbaos = new ByteArrayOutputStream();
+ try {
+ BufferedImage image = ImageIO.read(input);
+ BufferedImage cropped = image.getSubimage(rect[0],rect[1],rect[2],rect[3]);
+
+ ImageIO.write(cropped, format, imgbaos);
+
+ } catch (IOException e2) {
+ e2.printStackTrace();
+ } finally {
+ try {
+ input.close();
+ imgbaos.flush();
+ imgbaos.close();
+ } catch (IOException e3) {
+ e3.printStackTrace();
+ }
+ }
+ return imgbaos;
+ }
+ public static ByteArrayOutputStream pixelize(ByteArrayInputStream input, String format, int[] rect, int PIX_SIZE){
+ ByteArrayOutputStream imgbaos = new ByteArrayOutputStream();
+ try {
+ BufferedImage image = ImageIO.read(input);
+ Raster src = image.getData();
+ WritableRaster dest = src.createCompatibleWritableRaster();
+ double[] pixel = new double[3];
+ for(int y=0;y