/******************************* Copyright notice ******************************* Copyright (C)2002 by Andrei Loskutov <loskutov@gmx.de>. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. 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. THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. ********************************************************************************/ package adiag.gui; import java.awt.Color; import java.awt.Cursor; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.image.BufferedImage; import java.util.HashMap; import java.util.Observable; import javax.swing.Action; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JPopupMenu; import javax.swing.RepaintManager; import javax.swing.SwingUtilities; import javax.swing.ToolTipManager; import adiag.connection.Configuration; import adiag.model.Const; import adiag.model.Version; import adiag.view.LayoutManager; import adiag.view.Toolz; import adiag.view.VersionView; import adiag.view.View; /** * The "main" view panel class, with all versions etc. * @author Andy the Great */ public class ViewPanel extends JComponent implements View { /** used Cursor - Objekt */ public static final Cursor CURSOR_WAIT = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); /** used Cursor - Objekt */ public static final Cursor CURSOR_DEFAULT = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR); /** used Cursor - Objekt */ public static final Cursor CURSOR_MOVE = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); /** used Cursor - Objekt */ public static final Cursor CURSOR_HAND = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR); /** used Cursor - Objekt */ public static final Cursor CURSOR_CROSSHAIR = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); /** current second clicked version, for diff */ private VersionView diffView_two; /** menu for selected version */ protected JPopupMenu popupEdit; /** menu for background click */ protected JPopupMenu popupView; /** last x, y mouse-Coordinates by click */ private int prevx; /** last x, y mouse-Coordinates by click */ private int prevy; /** last x, y mouse-Coordinates by drag */ private int drag_x; /** last x, y mouse-Coordinates by drag */ private int drag_y; /** if we even change zoom from 1 to +- */ private boolean image_scaled; /** x - scale factor for view */ private double scale_x_axis = 1; /** y - scale factor for view */ private double scale_y_axis = 1; /** painting context size */ private Dimension backSize; /** all known actions */ private HashMap actions = new HashMap(13); /** my config instance */ private Configuration app; /** class to create menus */ private MenuCreator menuCreator; /** panel to show/view options */ private PropertiesPanel props_pnl; /** offscreen image */ private BufferedImage backBuffer; /** painting context */ private Graphics2D backGC; /** flag, to create new offscreen buffer */ protected boolean need_new_buffer; /** flag, if we change offscreen location by zoom */ protected boolean offscreen_location_scaled; /** used by error handling with offscreen buffer */ protected boolean error_by_make_buffer; /** used by error handling with offscreen buffer */ private int h_size_dividor = 1; /** curent screen size */ private Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); /** Really existing image size for offscreen painting, it may be smaller then * really needed size for layout all information. */ private Dimension offscreenSize = new Dimension(screenSize.width*2, screenSize.height*2); /** position of left upper corner of offscreen image in entire layout space */ private Point offscreenLocation = new Point(0,0); private KeyServer keyServer; private static Boolean is141; private BranchView branchView; /** * See return description * @return true, if JRE Version >= 1.3 ist */ public static boolean is141() { if(is141 == null){ String os = System.getProperty("java.vm.version", "1.4.1"); //System.out.println(os); is141 = new Boolean(os.startsWith("1.4.1")); } return is141.booleanValue(); } public int getPlatform(){ return View.PLATFORM_SWING; } public ViewPanel(Configuration app) { super(); this.app = app; keyServer = new KeyServer(actions); branchView = new BranchView(app); branchView.addObserver(this); addKeyListener(keyServer); //setDoubleBuffered(false); backSize = new Dimension(100, 100); this.setBackground(Color.white); this.setForeground(Color.black); ToolTipManager t = ToolTipManager.sharedInstance(); t.setDismissDelay(1000000); addMouseListener(t); addMouseMotionListener(t); menuCreator = new MenuCreator(this, app); popupView = menuCreator.createViewPopup(); popupEdit = menuCreator.createEditPopup(); String command = Commands.COMMAND_HOME; SimpleAction a = new SimpleAction(command) { public void actionPerformed(ActionEvent e) { Rectangle r = getVisibleRect(); r.x = 0; r.y = 0; scrollRectToVisible(r); } }; actions.put(command, a); command = Commands.COMMAND_END; a = new SimpleAction(command) { public void actionPerformed(ActionEvent e) { Rectangle r = getVisibleRect(); r.x = getPreferredSize().width; r.y = getPreferredSize().height; scrollRectToVisible(r); } }; actions.put(command, a); addMouseListener(new MouseListenerServer()); addMouseMotionListener(new MouseMotionServer()); setRequestFocusEnabled(true); //setAutoscrolls(true); //requestFocus(); } /** * Init layout too * @param versions die zu zeichnende Versionen * @param app akuelle Fensterinstanz */ public ViewPanel(Version[] versions, Configuration app) { this(app); setData(versions); } public void setData(Version[] versions) { branchView.setLayout(LayoutManager.createLayout(versions, this)); branchView.refreshLayout(false); } public void dispose(){ if(branchView!=null){ branchView.getLayout().setVersions(new Version[0]); } if(backGC!=null){ backGC.dispose(); backGC = null; backBuffer = null; } } /** * @see Component#setCursor(Cursor) */ public void setCursor(Cursor c) { if (!this.getCursor().equals(c)) { super.setCursor(c); } } /** Check, if given event the 'popup'- event on operation system * (i.e.: Linux:pressed, Windows:released), and shows then context-sensitive menu * (or not ;)). * @param e MouseEvent */ private void maybeShowPopup(MouseEvent e) { int x, y; if (e.isPopupTrigger()) { x = e.getX(); y = e.getY(); Action a; // click on revision if (branchView.getClicked() != null) { Version v = branchView.getClicked().getVersion(); a = (Action) actions.get(Commands.COMMAND_EXPLORE_ONE_BRANCH); if (v != null && (!v.isReceived() || !v.isChangeNumOk()) && !app.isOffline()) { if (a != null) { a.setEnabled(true); } } else { if (a != null) { a.setEnabled(false); } } a = (Action) actions.get(Commands.COMMAND_DIFF); if (v != null && !Const.TYPE_DELETE.equals(v.getChangeType()) && !app.isOffline()) { if (a != null) { a.setEnabled(true); } } else { if (a != null) { a.setEnabled(false); } } popupEdit.show(this, x, y); } // click on background else { String[] ubr = app.getConnector().getUnknownBranches(true); a = (Action) actions.get(Commands.COMMAND_EXPLORE_ALL_BRANCHES); if (ubr != null && ubr.length > 0 && !app.isOffline()) { if (a != null) { a.setEnabled(true); } } else { if (a != null) { a.setEnabled(false); } } popupView.show(this, x, y); } } } /** See return description * @return Dimension dimension of offscreen image * @see Component#getPreferredSize() */ public Dimension getPreferredSize() { if (backSize == null) { backSize = new Dimension(100, 100); return backSize; } else { Rectangle r = branchView.getLayout().getBounds(); return new Dimension((int) (r.getWidth() * scale_x_axis), (int) (r.getHeight() * scale_y_axis)); } } /** * Returns true if this component tiles its children -- that is, if * it can guarantee that the children will not overlap. The * repainting system is substantially more efficient in this * common case. JComponent subclasses that can't make this * guarantee, such as JLayeredPane, should override this method * to return false. * return true if this component's children don't overlap * @see JComponent#isOptimizedDrawingEnabled() * @return always true */ public boolean isOptimizedDrawingEnabled() { return super.isOptimizedDrawingEnabled();//true; } /** * Overriden, see return description * Returns true if this component is completely opaque. * <p> * An opaque component paints every pixel within its * rectangular bounds. A non-opaque component paints only a subset of * its pixels or none at all, allowing the pixels underneath it to * "show through". Therefore, a component that does not fully paint * its pixels provides a degree of transparency. * <p> * Subclasses that guarantee to always completely paint their contents * should override this method and return true. * * return true if this component is completely opaque * * @return always true * @see Component#isOpaque() */ public boolean isOpaque() { return true; } /** * Overriden to paint custom component content * @see JComponent#paintComponent(Graphics) * @param g painting context */ public void paintComponent(Graphics g) { //super.paintComponent(g); if (g != null) { if (branchView.getLayout() != null) { if(backGC == null){ branchView.setNeed_re_paint(true); } if (branchView.isNeed_re_paint()) { if (backGC != null) { if(scale_x_axis != 0 && scale_y_axis != 0){ backGC.clearRect(-offscreenLocation.x, -offscreenLocation.y, - (int)((offscreenLocation.x - offscreenSize.width)/scale_x_axis), - (int)((offscreenLocation.y - offscreenSize.height)/scale_y_axis)); } } else { newBackBuffer(offscreenSize); } branchView.setNeed_re_paint(false); this.need_new_buffer = false; branchView.getLayout().paint(backGC); } Point p = getRightLocation(); Graphics2D gr = (Graphics2D) g; //gr.setClip(null); gr.setBackground(Color.white); gr.clearRect(p.x, p.y, offscreenSize.width, offscreenSize.height); gr.drawImage(backBuffer, p.x, p.y, this); } } } /** * Create new offscreen image * @param r new offscreen dimensions */ private void newBackBuffer(Dimension r) { Graphics2D old_backGC = backGC; BufferedImage new_backBuffer = null; Graphics2D new_backGC = null; // we can have OutOfMemoryError here, if image size is too large... try { new_backBuffer = new BufferedImage(r.width, r.height, BufferedImage.TYPE_USHORT_565_RGB); new_backGC = (Graphics2D) new_backBuffer.getGraphics(); new_backGC.setBackground(Color.white); new_backGC.clearRect(0, 0, r.width, r.height); backSize = new Dimension(r.width, r.height); backGC = new_backGC; backBuffer = new_backBuffer; if (old_backGC != null) { old_backGC.dispose(); } // refresh point of view checkAndMoveOffscreen(); System.runFinalization(); System.gc(); if (error_by_make_buffer) { setPreferredSize(new Dimension(r.width, r.height)); } h_size_dividor = 1; error_by_make_buffer = false; Const.H_SPACE = Const.H_SPACE_D; } catch (Throwable e) { h_size_dividor++; error_by_make_buffer = true; e.printStackTrace(); if (old_backGC != null) { old_backGC.dispose(); old_backGC = null; } if (new_backGC != null) { new_backGC.dispose(); new_backGC = null; } System.runFinalization(); System.gc(); if(!error_by_make_buffer){ // first time Action a = (Action) actions.get(Commands.COMMAND_COLLAPSE_ALL); a.actionPerformed(new ActionEvent(this, -1, Commands.COMMAND_COLLAPSE_ALL)); } if (h_size_dividor < 3) { JOptionPane.showMessageDialog( app.getJComponent(), "\nImage size is too large, sorry", "View: exception occured during creating new buffer for image!", JOptionPane.ERROR_MESSAGE); Const.H_SPACE = Const.V_SPACE; branchView.getLayout().doLayout(); Dimension r2 = screenSize;//layout.getBounds(); this.backSize = new Dimension(r2.width, r2.height); newBackBuffer(r2); } } } /** Overriden * @param x the 0 - coordinate on the x - axis * @param y the 0 - coordinate on the y - axis * @see Component#setLocation(int, int) */ public void setLocation(int x, int y) { super.setLocation(x, y); // -xxx , -yyy //System.out.println("new location to x:" + x + ", y:" + y); //Rectangle r = new Rectangle(x, y, 100, 100); checkAndMoveOffscreen(); //if(true){ //System.out.println("view position before:" + scrollComponent.getViewport().getViewPosition()); //scrollComponent.getViewport().scrollRectToVisible(r); //System.out.println("view position after:" + scrollComponent.getViewport().getViewPosition()); //} } /** * Check, if we need to move current offscreen position to the next one, * and then do this. * @return boolean true, if screen position was changed */ private boolean checkAndMoveOffscreen() { Point nextLocation = getNextOffscreenLocation(); boolean changed = !offscreenLocation.equals(nextLocation); if(changed){ if(backGC == null){ return false; } //System.out.println("move offscreen!!!"); //int dx = nextLocation.x - offscreenLocation.x; //int dy = nextLocation.y - offscreenLocation.y; //backGC.translate(dx, dy); backGC.translate(-offscreenLocation.x, -offscreenLocation.y); backGC.translate(nextLocation.x, nextLocation.y); branchView.setNeed_re_paint(true); // store current image position offscreenLocation = nextLocation; } //SwingUtilities.invokeLater(new Runnable() { // public void run() { //revalidate(); // @todo must be enabled? repaint(); // } //}); return changed; } /** * See return description * @return Point with new calculated "viewable window" on offscreen position, * based on current location of panel in scrollpane. This may be old position, * if viewable piece fit to offscreen window position, or new position, never null. */ private Point getNextOffscreenLocation(){ // if 'layout size' fit to screen, do nothing // preferred is already multiplied with zoom Dimension d = getPreferredSize(); if(d.width <= offscreenSize.width && d.height<= offscreenSize.height){ return new Point(0,0); } // 1) we have back screen, witch 2x bigger as size of screenSize // and screenSize is maximum of 'visible' screen size // if visible position + window height(width) is over this back screen // lower(upper) bounds, we need redraw back screen Point upp_left_vis = getLocation(null); Rectangle visible_loc = getVisibleRect(); // visible is not multiplied with zoom, also we must change it? Point low_right_vis = new Point ( upp_left_vis.x - visible_loc.width , upp_left_vis.y - visible_loc.height); // real point Point low_right_hidd = new Point ( offscreenLocation.x - offscreenSize.width, offscreenLocation.y - offscreenSize.height); Point result = new Point(offscreenLocation); boolean changed =false;//offscreen_location_scaled; int dx = (int)(offscreenSize.width * 0.5); int dy = (int)(offscreenSize.height * 0.5); // x coordinate first if(upp_left_vis.x > offscreenLocation.x){ result.x = offscreenLocation.x + dx; changed = true; } else if(low_right_vis.x < low_right_hidd.x){ result.x = offscreenLocation.x - dx; changed = true; } // y coordinate if(upp_left_vis.y > offscreenLocation.y){ result.y = offscreenLocation.y + dy; changed = true; } else if(low_right_vis.y < low_right_hidd.y){ result.y = offscreenLocation.y - dy; changed = true; } if(changed){ //System.out.println("***need repaint:" + result); offscreen_location_scaled = false; return result; } else { return offscreenLocation; } } /** * See return description * @return Point position on paint context with offscreen corrections */ private Point getRightLocation(){ Point current_vis = getLocation(null); current_vis.x = (int)(current_vis.x - offscreenLocation.x); current_vis.y = (int)(current_vis.y - offscreenLocation.y); return current_vis; } /** Overriden * @param p New position * @see Component#setLocation(Point) */ public void setLocation(Point p) { this.setLocation(p.x, p.y); } /** Overriden * @param d new dimensions * @see JComponent#setPreferredSize(Dimension) */ public void setPreferredSize(Dimension d) { backSize = d; branchView.setNeed_re_paint(true); //need_new_buffer = true; checkAndMoveOffscreen(); revalidate(); repaint(); } /** * See return description * @return String extended version information, if available * @param e MouseEvent with current mouse coordinates */ public String getToolTipText(MouseEvent e) { // if in getBounds() setLocation not used!!! //Point p = getLocation(); int x = e.getX();// + p.x; int y = e.getY();// + p.y; int[] xy = fromScreenToLayout(x, y); String text = branchView.getLayout().getInfo(xy[0], xy[1]); return text; } /** * Convert view coordinates to the layout - coordinates * @return int[] the x, y Layout - coordinates * @param x int the x - coordinate from view * @param y int the y - coordinate from view */ private int[] fromScreenToLayout(int x, int y) { if (scale_x_axis > 0) { //x = (int) (x / scale_x_axis); x = (int)((x + offscreenLocation.x) / scale_x_axis - offscreenLocation.x); } if (scale_y_axis > 0) { //y = (int) (y / scale_y_axis); y = (int)((y + offscreenLocation.y) / scale_y_axis - offscreenLocation.y); } return new int[] { x, y}; } /** * Convert layout coordinates to the view - coordinates * @return int[] the x, y screen - coordinates * @param x int the x - coordinate from layout * @param y int the y - coordinate from layout */ private int[] fromLayoutToScreen(double x, double y) { if (scale_x_axis > 0) { x = ((x + offscreenLocation.x) * scale_x_axis - offscreenLocation.x); } if (scale_y_axis > 0) { y = ((y + offscreenLocation.y) * scale_y_axis - offscreenLocation.y); } return new int[] { (int)x, (int)y}; } /** * Set the skale faktor on the x - axis * @param newScale_x_axis float the new skale faktor on the x - axis */ public void setScale_x_axis(double newScale_x_axis) { if (newScale_x_axis > 0){ if(backGC != null && scale_x_axis != 0){ double sx = newScale_x_axis / scale_x_axis; if(sx != 1){ backGC.translate(-offscreenLocation.x,-offscreenLocation.y); backGC.scale(sx, 1); backGC.translate(offscreenLocation.x, offscreenLocation.y); scale_x_axis *= sx; offscreen_location_scaled = true; } } } } /** * Set the skale faktor on the y - axis * @param newScale_y_axis float the new skale faktor on the y - axis */ public void setScale_y_axis(double newScale_y_axis) { if (newScale_y_axis > 0){ if(backGC != null && scale_y_axis != 0){ double sy = newScale_y_axis / scale_y_axis; if(sy != 1){ backGC.translate(-offscreenLocation.x,-offscreenLocation.y); backGC.scale(1, sy); backGC.translate(offscreenLocation.x, offscreenLocation.y); scale_y_axis *= sy; offscreen_location_scaled = true; } } } } /** * Zoom in/out * @param sx scale factor on the x axis * @param sy scale factor on the y axis */ void zoom(double sx, double sy){ //Point p = getLocation(); //System.out.println("zoom: get location before:" + p); // first, we need change here location point (anchor) if needed setScale_x_axis(sx); setScale_y_axis(sy); //setLocation((int)(offscreenLocation.x * scale_x_axis), (int)(offscreenLocation.y * scale_y_axis)); //Rectangle r = new Rectangle(-p.x, -p.y, 100, 100); branchView.setNeed_re_paint(true); // second, we need move offscreen, if location was changed checkAndMoveOffscreen(); //if(true){ //System.out.println("view position before:" + scrollComponent.getViewport().getViewPosition()); //scrollComponent.getViewport().scrollRectToVisible(r); //System.out.println("view position after:" + scrollComponent.getViewport().getViewPosition()); //} if(is141()){ RepaintManager repaintManager = RepaintManager.currentManager(ViewPanel.this.getParent()); repaintManager.markCompletelyDirty((JComponent)ViewPanel.this.getParent()); repaintManager.paintDirtyRegions(); } repaint(); //System.out.println("zoom: "); } /** * Class to administrate mouse motion * @author Andy the Great */ protected class MouseMotionServer implements MouseMotionListener { /** * Constructor for MouseMotionServer. */ public MouseMotionServer() { super(); } /** Mouse was dragged.... * @param e MouseEvent * @see MouseMotionListener#mouseDragged(MouseEvent) */ public void mouseDragged(MouseEvent e) { int x = e.getX();// + p.x; int y = e.getY();// + p.y; VersionView clicked = branchView.getClicked(); if (clicked != null) { branchView.setMoved( new VersionView[] { clicked } ); if (keyServer.isKeyPressed(KeyEvent.VK_CONTROL) && !keyServer.isKeyPressed(KeyEvent.VK_SHIFT) || SwingUtilities.isRightMouseButton(e)) { branchView.setMoved( Toolz.getAllFromPath(clicked)); } else if (keyServer.isKeyPressed(KeyEvent.VK_CONTROL) && keyServer.isKeyPressed(KeyEvent.VK_SHIFT)) { branchView.setMoved( (VersionView[]) branchView.getLayout().getElements().toArray( new VersionView[branchView.getLayout().getElements().size()])); } VersionView [] moved = branchView.getMoved(); float[] min_xy = Toolz.findMin(moved); int[] xy = fromScreenToLayout(x, y); double dx = xy[0] - (clicked.getX() + prevx); // double dy = xy[1] - (clicked.getY() + prevy); // dx = dx + min_xy[0] < 0 ? 0 : dx; dy = dy + min_xy[1] < 0 ? 0 : dy; for (int i = 0; i < moved.length; i++) { moved[i].dx += dx; moved[i].dy += dy; } // e.consume(); branchView.setNeed_re_paint(true); //paintImmediately(0, 0, getWidth(), getHeight()); //@workaround for 1.4.1 if(is141()){ RepaintManager repaintManager = RepaintManager.currentManager(ViewPanel.this.getParent()); repaintManager.markCompletelyDirty((JComponent)ViewPanel.this.getParent()); repaintManager.paintDirtyRegions(); /*SwingUtilities.invokeLater(new Runnable() { public void run() { RepaintManager repaintManager = RepaintManager.currentManager(ViewPanel.this); repaintManager.markCompletelyDirty(ViewPanel.this); //revalidate(); repaint(); } });*/ } // end w repaint(); } else { int dx, dy; Rectangle r = getVisibleRect(); // @todo hack because hacked getBounds() Point p = getLocation(null); r.setLocation(-p.x, -p.y); dx = - (int) (drag_x - x); drag_x = x; dy = - (int) (drag_y - y); drag_y = y; r.x += dx / 2; r.y += dy / 2; scrollRectToVisible(r); //e.consume(); //paintImmediately(0, 0, getWidth(), getHeight()); //@workaround for 1.4.1 //zoom(0,0); // end w if(is141()){ RepaintManager repaintManager = RepaintManager.currentManager(ViewPanel.this.getParent()); repaintManager.markCompletelyDirty((JComponent)ViewPanel.this.getParent()); repaintManager.paintDirtyRegions(); //System.out.println("1.4.1"); /*SwingUtilities.invokeLater(new Runnable() { public void run() { revalidate(); repaint(); } }); */ } repaint(); } } /** * Mouse was moved... * @param e MouseEvent * @see MouseMotionListener#mouseMoved(MouseEvent) */ public void mouseMoved(MouseEvent e) { //Point p = getLocation(); int x = e.getX();// + p.x; int y = e.getY();// + p.y; int[] xy = fromScreenToLayout(x, y); VersionView v = branchView.getLayout().getVersionView(xy[0], xy[1]); VersionView diffView = branchView.getDiffView(); if (v != null) { if (diffView != null && diffView != null && !Const.TYPE_DELETE.equals(branchView.getClicked().getVersion().getChangeType())) { setCursor(CURSOR_CROSSHAIR); } else { setCursor(CURSOR_HAND); } } else { setCursor(CURSOR_DEFAULT); } if (diffView != null) { paintImmediately(0, 0, getWidth(), getHeight()); xy = fromLayoutToScreen(diffView.getX(), diffView.getY()); getGraphics().drawLine( xy[0], xy[1], x , y ); } } } /** * Class to administrate mouse clicks * @author Andy the Great */ public class MouseListenerServer implements MouseListener { /** * Overriden from interface, not used * @param e MouseEvent * @see MouseListener#mouseEntered(MouseEvent) */ public void mouseEntered(MouseEvent e) {} /** * Overriden from interface, not used * @param e MouseEvent * @see MouseListener#mouseExited(MouseEvent) */ public void mouseExited(MouseEvent e) {} /** Mouse was pressed... * @param e MouseEvent * @see MouseListener#mousePressed(MouseEvent) */ public void mousePressed(MouseEvent e) { //Point p = getLocation(); int x = e.getX();// + p.x; int y = e.getY();// + p.y; branchView.setClicked( null ); branchView.setMoved(null); prevx = (drag_x = x); prevy = (drag_y = y); int[] xy = fromScreenToLayout(prevx, prevy); branchView.setClicked( branchView.getLayout().getVersionView(xy[0], xy[1])); // Abweichung zwischen dem klickpunkt und der koordinate des objektes if (branchView.getClicked()!= null) { prevx = xy[0] - (int) branchView.getClicked().getX(); prevy = xy[1] - (int) branchView.getClicked().getY(); } else { setCursor(CURSOR_MOVE); } maybeShowPopup(e); } /** Mouse was released... * @param e * @see MouseListener#mouseReleased(MouseEvent) */ public void mouseReleased(MouseEvent e) { VersionView [] moved = branchView.getMoved(); if (moved != null && moved.length > 0) { Point max = branchView.getLayout().getMax(); float extra_width = Const.H_SPACE * 2; float extra_height = Const.V_SPACE * 2; double x, y = 0; for (int i = 0; i < moved.length; i++) { x = moved[i].getX(); y = moved[i].getY(); if (x + extra_width > max.x) { max.x = (int) (x + extra_width); branchView.getLayout().setMax(max); } if (y + extra_height > max.y) { max.y = (int) (y + extra_height); branchView.getLayout().setMax(max); } } Dimension dim = new Dimension(max.x, max.y); // - min.x - min.y if (!dim.equals(backSize)) { setPreferredSize(dim); } } else { maybeShowPopup(e); } if (branchView.getClicked() != null) { setCursor(CURSOR_HAND); } else { setCursor(CURSOR_DEFAULT); } //revalidate(); //repaint(); //setLocation(getLocation()); //paintComponent(getGraphics()); } /** Mouse was clicked... * @see MouseListener#mouseClicked(MouseEvent) */ public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 1) { if (branchView.getClicked() == null) { setCursor(CURSOR_DEFAULT); if (branchView.getDiffView() != null) { branchView.getDiffView().setSelected(false); branchView.setDiffView(null); branchView.setNeed_re_paint(true); } if (diffView_two != null) { diffView_two.setSelected(false); diffView_two = null; branchView.setNeed_re_paint(true); } } else if (!Const.TYPE_DELETE.equals(branchView.getClicked().getVersion().getChangeType())) { // delete selection if (branchView.getDiffView() != null) { if (!branchView.getDiffView().equals(branchView.getClicked())) { try { app.getConnector().diff(branchView.getDiffView().getVersion(), branchView.getClicked().getVersion()); } catch (Exception ee) { app.error("Cannot perform diff operation:\n" + ee.getMessage(), ee); } if (diffView_two != null) { diffView_two.setSelected(false); } diffView_two = branchView.getClicked(); diffView_two.setSelected(true); } else { // dieselbe version branchView.getDiffView().setSelected(false); branchView.setDiffView(null); if (diffView_two != null) { diffView_two.setSelected(false); diffView_two = null; } } branchView.setNeed_re_paint(true); } else { // make first selected branchView.setDiffView(branchView.getClicked()); branchView.getDiffView().setSelected(true); branchView.setNeed_re_paint(true); // @todo workaround for menu disappear if(is141()){ setCursor(CURSOR_CROSSHAIR); } } } } else if (e.getClickCount() == 2 && branchView.getClicked() != null) { Version v = branchView.getClicked().getVersion(); if (v != null && (!v.isReceived() || !v.isChangeNumOk()) && !app.isOffline()) { Action a = (Action) actions.get(Commands.COMMAND_EXPLORE_ONE_BRANCH); if (a != null) { a.actionPerformed(new ActionEvent(this, 0, "run it")); } } if (branchView.getDiffView() != null) { branchView.getDiffView().setSelected(false); } if (diffView_two != null) { diffView_two.setSelected(false); } diffView_two = null; branchView.setDiffView(null); branchView.setNeed_re_paint(true); } drag_x = 0; drag_y = 0; // @todo workaround for menu disappear if(is141()){ branchView.setNeed_re_paint(true); RepaintManager repaintManager = RepaintManager.currentManager(ViewPanel.this.getParent()); repaintManager.markCompletelyDirty((JComponent)ViewPanel.this.getParent()); repaintManager.paintDirtyRegions(); } repaint(); } /** * Constructor for MouseListenerServer. */ public MouseListenerServer() { super(); } } /** Overriden * @return one rectangle, that has always 0,0 x,y coordinates and * the width and height of the view * @see java.awt.Component#getBounds(Rectangle) */ public Rectangle getBounds(Rectangle rv) { //return super.getBounds(rv); // @todo hack on getbounds if(rv == null){ rv = new Rectangle(); } // 0,0: this is a hack to handle wrong size of scrollpane !! rv.setBounds( 0, 0, getWidth(), getHeight() ); return rv; } /** Overriden * @return view dimension * @see java.awt.Component#getMaximumSize() */ public Dimension getMaximumSize() { return getPreferredSize(); } /** Overriden * @return view dimension * @see java.awt.Component#getMinimumSize() */ public Dimension getMinimumSize() { return getPreferredSize(); } /** Overriden * Whether the receiving component should use a buffer to paint. If set to * true, all the drawing from this component will be done in an offscreen * painting buffer. The offscreen painting buffer will the be copied onto * the screen. Swing's painting system always use a maximum of one double * buffer. If a Component is buffered and one of its ancestor is also * buffered, the ancestor buffer will be used. * * @return always false * @see java.awt.Component#isDoubleBuffered() */ public boolean isDoubleBuffered() { return super.isDoubleBuffered();//false; } /** Overriden * @return always true * @see javax.swing.JComponent#isMaximumSizeSet() */ public boolean isMaximumSizeSet() { return true; } /** Overriden * @return always true * @see javax.swing.JComponent#isMinimumSizeSet() */ public boolean isMinimumSizeSet() { return true; } /** Overriden * @return always true * @see javax.swing.JComponent#isPreferredSizeSet() */ public boolean isPreferredSizeSet() { return true; } /** Overriden * @return always true * @see javax.swing.JComponent#isRequestFocusEnabled() */ public boolean isRequestFocusEnabled() { return true; } /** * Update view after redo layout * @param changeOffscreenLocation currently not used */ public void refreshViewAfterDoLayout(boolean changeOffscreenLocation) { Rectangle r = branchView.getLayout().getBounds(); Dimension d = new Dimension(r.width, r.height); /*if(changeOffscreenLocation){ this.offscreen_location_scaled = false; if(backGC != null){ backGC.translate(-offscreenLocation.x, -offscreenLocation.y); } this.offscreenLocation = new Point(0,0); this.setLocation(0,0); }*/ setPreferredSize(d); ((App)app.getJComponent()).setBestAppSizeAndLocation(d); repaint(); } /** * Returns the props_pnl. * @return PropertiesPanel */ public PropertiesPanel getProps_pnl() { return props_pnl; } /** * Sets the props_pnl. * @param props_pnl The props_pnl to set */ public void setProps_pnl(PropertiesPanel props_pnl) { this.props_pnl = props_pnl; } /** * Returns the actions. * @return HashMap */ public HashMap getActions() { return actions; } /** * Returns the branchView. * @return BranchView */ public BranchView getBranchView() { return branchView; } /* (non-Javadoc) * @see java.util.Observer#update(java.util.Observable, java.lang.Object) */ public void update(Observable o, Object arg) { if(Commands.COMMAND_REDO_LAYOUT.equals(arg)){ this.refreshViewAfterDoLayout(false); } } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#5 | 2735 | andrei_loskutov | sources are now included to binary distribution at http://andrei.gmxhome.de/perforce/index.html | ||
#4 | 2554 | andrei_loskutov |
#25.12.2002 23:29 Revision 1.3.0.4 beta 1) Some small refactoring 2) First integration with P4eclipse: properties etc, thanks Boris Pr�ssmann 5) Better integration to Eclipse: use Eclipse internal compare tool for diff. 6) Fix some minor bugs. #14.12.2002 23:15 Revision 1.3.0.3 beta 1) Fix endless loop bug if p4 path was not set. 2) Fix never getting focus bug after error message shown 3) Fix painting bug on JDK 1.4.1 (must be verified!!!) 4) Some small refactoring 5) Fix error handling. 6) Fix some minor bugs. |
||
#3 | 2552 | andrei_loskutov | 1.3.0.4 changes | ||
#2 | 2460 | andrei_loskutov |
1) Change configuration: always reed properties 2) Change password store to hex format/password field 3) Create standalone/not standalone state for new branchview eclipse wrapper 4) Refactor all main classes to remove cyclic package dependency 5) Add workaround to fix new JDK 1.4.1 Swing bugs on JScrollPane/JViewPort 6) Add dispose methods to panel/connector 7) Minor internal GUI fixes/refactorings |
||
#1 | 2222 | andrei_loskutov |
#13.10.2002 22:16 Revision 1.2.1 1) Documentation task is finished... Yes!!! 2) New feature: copy P4 depot path 3) Some small fixes to menu shortkeys belongs ctrl + c and ctrl + d 4) Clipboard fix because of JDK 1.2 - 1.3 bug 5) Smallest refactoring on some methods. 6) Html help updated |