mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Animated pinch zoom.
This commit is contained in:
@@ -18,14 +18,16 @@ package com.intellij.ui.components;
|
||||
import com.intellij.ui.table.JBTable;
|
||||
import com.intellij.util.ui.ComponentWithEmptyText;
|
||||
import com.intellij.util.ui.StatusText;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
|
||||
public class JBViewport extends JViewport {
|
||||
public class JBViewport extends JViewport implements ZoomableViewport {
|
||||
private StatusText myEmptyText;
|
||||
private ZoomingDelegate myZoomer;
|
||||
|
||||
public JBViewport() {
|
||||
addContainerListener(new ContainerListener() {
|
||||
@@ -50,16 +52,40 @@ public class JBViewport extends JViewport {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return super.getPreferredSize(); //To change body of overridden methods use File | Settings | File Templates.
|
||||
public void paint(Graphics g) {
|
||||
if (myZoomer != null && myZoomer.isActive()) {
|
||||
myZoomer.paint(g);
|
||||
}
|
||||
else {
|
||||
super.paint(g);
|
||||
|
||||
if (myEmptyText != null) {
|
||||
myEmptyText.paint(this, g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Magnificator getMagnificator() {
|
||||
JComponent view = (JComponent)getView();
|
||||
return view != null ? (Magnificator)view.getClientProperty(Magnificator.CLIENT_PROPERTY_KEY) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
public void magnificationStarted(Point at) {
|
||||
myZoomer = new ZoomingDelegate((JComponent)getView(), this);
|
||||
myZoomer.magnificationStarted(at);
|
||||
}
|
||||
|
||||
if (myEmptyText != null) {
|
||||
myEmptyText.paint(this, g);
|
||||
}
|
||||
@Override
|
||||
public void magnificationFinished(double magnification) {
|
||||
myZoomer.magnificationFinished(magnification);
|
||||
myZoomer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void magnify(double magnification) {
|
||||
myZoomer.magnify(magnification);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface Magnificator {
|
||||
Key CLIENT_PROPERTY_KEY = Key.create("MagnifiableComponent");
|
||||
Point magnify(double scale, Point at);
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface ZoomableViewport {
|
||||
@Nullable
|
||||
Magnificator getMagnificator();
|
||||
void magnificationStarted(Point at);
|
||||
void magnificationFinished(double magnification);
|
||||
void magnify(double magnification);
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.ui.Gray;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
public class ZoomingDelegate {
|
||||
private final JComponent myContentComponent;
|
||||
private final JComponent myViewportComponent;
|
||||
|
||||
private BufferedImage myCachedImage;
|
||||
private Point myMagnificationPoint;
|
||||
private double myMagnification;
|
||||
|
||||
public ZoomingDelegate(JComponent contentComponent, JComponent viewportComponent) {
|
||||
myContentComponent = contentComponent;
|
||||
myViewportComponent = viewportComponent;
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
if (myCachedImage != null && myMagnificationPoint != null && myMagnification != 0) {
|
||||
double scale = magnificationToScale(myMagnification);
|
||||
int xoffset = (int)(myMagnificationPoint.x - myMagnificationPoint.x * scale);
|
||||
int yoffset = (int)(myMagnificationPoint.y - myMagnificationPoint.y * scale);
|
||||
|
||||
Rectangle clip = g.getClipBounds();
|
||||
|
||||
g.setColor(Gray._120);
|
||||
g.fillRect(clip.x, clip.y, clip.width, clip.height);
|
||||
|
||||
Graphics2D translated = (Graphics2D)g.create();
|
||||
translated.translate(xoffset, yoffset);
|
||||
translated.scale(scale, scale);
|
||||
|
||||
translated.drawImage(myCachedImage, 0, 0, null);
|
||||
}
|
||||
}
|
||||
|
||||
public void magnificationStarted(Point at) {
|
||||
myMagnificationPoint = at;
|
||||
}
|
||||
|
||||
public void magnificationFinished(double magnification) {
|
||||
if (myMagnification != 0) {
|
||||
Magnificator magnificator = ((ZoomableViewport)myViewportComponent).getMagnificator();
|
||||
|
||||
if (magnificator != null) {
|
||||
Point inContent = convertToContentCoordinates(myMagnificationPoint);
|
||||
|
||||
final Point inContentScaled = magnificator.magnify(magnificationToScale(magnification), inContent);
|
||||
|
||||
int voffset = inContentScaled.y - myMagnificationPoint.y;
|
||||
int hoffset = inContentScaled.x - myMagnificationPoint.x;
|
||||
myViewportComponent.repaint();
|
||||
myViewportComponent.validate();
|
||||
|
||||
scrollTo(voffset, hoffset);
|
||||
}
|
||||
}
|
||||
|
||||
myMagnificationPoint = null;
|
||||
myMagnification = 0;
|
||||
myCachedImage = null;
|
||||
}
|
||||
|
||||
protected void scrollTo(int voffset, int hoffset) {
|
||||
JViewport viewport = (JViewport)myViewportComponent;
|
||||
JScrollPane pane = (JScrollPane)viewport.getParent();
|
||||
JScrollBar vsb = pane.getVerticalScrollBar();
|
||||
vsb.setValue(voffset);
|
||||
JScrollBar hsb = pane.getHorizontalScrollBar();
|
||||
hsb.setValue(hoffset);
|
||||
}
|
||||
|
||||
protected Point convertToContentCoordinates(Point point) {
|
||||
return SwingUtilities.convertPoint(myViewportComponent, point, myContentComponent);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return myCachedImage != null;
|
||||
}
|
||||
|
||||
private static double magnificationToScale(double magnification) {
|
||||
return magnification < 0 ? 1f / (1 - magnification) : (1 + magnification);
|
||||
}
|
||||
|
||||
public void magnify(double magnification) {
|
||||
if (myMagnification != magnification) {
|
||||
myMagnification = magnification;
|
||||
|
||||
if (myCachedImage == null) {
|
||||
Rectangle bounds = myViewportComponent.getBounds();
|
||||
BufferedImage image = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
Graphics graphics = image.getGraphics();
|
||||
graphics.setClip(0, 0, bounds.width, bounds.height);
|
||||
myViewportComponent.paint(graphics);
|
||||
|
||||
myCachedImage = image;
|
||||
}
|
||||
}
|
||||
myViewportComponent.repaint();
|
||||
}
|
||||
}
|
||||
+44
-8
@@ -16,9 +16,16 @@
|
||||
package com.intellij.openapi.actionSystem.impl;
|
||||
|
||||
import com.apple.eawt.event.*;
|
||||
import com.intellij.openapi.actionSystem.ActionManager;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.wm.IdeFrame;
|
||||
import com.intellij.ui.components.Magnificator;
|
||||
import com.intellij.ui.components.ZoomableViewport;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
|
||||
/**
|
||||
* User: anna
|
||||
@@ -28,6 +35,7 @@ class MacGestureAdapter extends GestureAdapter {
|
||||
double magnification;
|
||||
private final IdeFrame myFrame;
|
||||
private MouseGestureManager myManager;
|
||||
private ZoomableViewport myMagnifyingViewport;
|
||||
|
||||
public MacGestureAdapter(MouseGestureManager manager, IdeFrame frame) {
|
||||
myFrame = frame;
|
||||
@@ -38,35 +46,63 @@ class MacGestureAdapter extends GestureAdapter {
|
||||
|
||||
@Override
|
||||
public void gestureBegan(GesturePhaseEvent event) {
|
||||
myManager.activateTrackpad();
|
||||
magnification = 0;
|
||||
|
||||
Point mouse = MouseInfo.getPointerInfo().getLocation();
|
||||
SwingUtilities.convertPointFromScreen(mouse, myFrame.getComponent());
|
||||
Component deepest = SwingUtilities.getDeepestComponentAt(myFrame.getComponent(), mouse.x, mouse.y);
|
||||
ZoomableViewport viewport = (ZoomableViewport) SwingUtilities.getAncestorOfClass(ZoomableViewport.class, deepest);
|
||||
if (viewport != null) {
|
||||
Magnificator magnificator = viewport.getMagnificator();
|
||||
|
||||
if (magnificator != null) {
|
||||
Point at = MouseInfo.getPointerInfo().getLocation();
|
||||
SwingUtilities.convertPointFromScreen(at, (JComponent)viewport);
|
||||
viewport.magnificationStarted(at);
|
||||
myMagnifyingViewport = viewport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void gestureEnded(GesturePhaseEvent event) {
|
||||
myManager.activateTrackpad();
|
||||
if (magnification != 0) {
|
||||
MouseGestureManager.processMagnification(myFrame, magnification);
|
||||
if (myMagnifyingViewport != null) {
|
||||
myMagnifyingViewport.magnificationFinished(magnification);
|
||||
myMagnifyingViewport = null;
|
||||
magnification = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipedLeft(SwipeEvent event) {
|
||||
myManager.activateTrackpad();
|
||||
myManager.processLeftSwipe(myFrame);
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
AnAction forward = actionManager.getAction("Forward");
|
||||
if (forward == null) return;
|
||||
|
||||
actionManager.tryToExecute(forward, createMouseEventWrapper(myFrame), null, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void swipedRight(SwipeEvent event) {
|
||||
myManager.activateTrackpad();
|
||||
myManager.processRightSwipe(myFrame);
|
||||
ActionManager actionManager = ActionManager.getInstance();
|
||||
AnAction back = actionManager.getAction("Back");
|
||||
if (back == null) return;
|
||||
|
||||
actionManager.tryToExecute(back, createMouseEventWrapper(myFrame), null, null, false);
|
||||
}
|
||||
|
||||
private static MouseEvent createMouseEventWrapper(IdeFrame frame) {
|
||||
return new MouseEvent(frame.getComponent(), ActionEvent.ACTION_PERFORMED, System.currentTimeMillis(), 0, 0, 0, 0, false, 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void magnify(MagnificationEvent event) {
|
||||
myManager.activateTrackpad();
|
||||
magnification += event.getMagnification();
|
||||
if (myMagnifyingViewport != null) {
|
||||
myMagnifyingViewport.magnify(magnification);
|
||||
}
|
||||
}
|
||||
|
||||
public void remove(JComponent cmp) {
|
||||
|
||||
+1
-36
@@ -39,14 +39,11 @@ import java.util.Map;
|
||||
public class MouseGestureManager implements ApplicationComponent {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("MouseGestureManager");
|
||||
private ActionManagerImpl myActionManager;
|
||||
|
||||
private Map<IdeFrame, Object> myListeners = new HashMap<IdeFrame, Object>();
|
||||
private boolean HAS_TRACKPAD = false;
|
||||
|
||||
|
||||
public MouseGestureManager(ActionManagerImpl actionManager) {
|
||||
myActionManager = actionManager;
|
||||
public MouseGestureManager() {
|
||||
}
|
||||
|
||||
public void add(final IdeFrame frame) {
|
||||
@@ -76,38 +73,6 @@ public class MouseGestureManager implements ApplicationComponent {
|
||||
return HAS_TRACKPAD;
|
||||
}
|
||||
|
||||
protected static void processMagnification(IdeFrame frame, double magnification) {
|
||||
Point mouse = MouseInfo.getPointerInfo().getLocation();
|
||||
SwingUtilities.convertPointFromScreen(mouse, frame.getComponent());
|
||||
Component componentAt = SwingUtilities.getDeepestComponentAt(frame.getComponent(), mouse.x, mouse.y);
|
||||
if (componentAt != null) {
|
||||
Editor editor = PlatformDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(componentAt));
|
||||
if (editor != null) {
|
||||
double currentSize = editor.getColorsScheme().getEditorFontSize();
|
||||
int defaultFontSize = EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize();
|
||||
((EditorEx)editor).setFontSize((int)(Math.max(currentSize + magnification * 3, defaultFontSize)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processLeftSwipe(IdeFrame frame) {
|
||||
AnAction forward = myActionManager.getAction("Forward");
|
||||
if (forward == null) return;
|
||||
|
||||
myActionManager.tryToExecute(forward, createMouseEventWrapper(frame), null, null, false);
|
||||
}
|
||||
|
||||
protected void processRightSwipe(IdeFrame frame) {
|
||||
AnAction back = myActionManager.getAction("Back");
|
||||
if (back == null) return;
|
||||
|
||||
myActionManager.tryToExecute(back, createMouseEventWrapper(frame), null, null, false);
|
||||
}
|
||||
|
||||
private static MouseEvent createMouseEventWrapper(IdeFrame frame) {
|
||||
return new MouseEvent(frame.getComponent(), ActionEvent.ACTION_PERFORMED, System.currentTimeMillis(), 0, 0, 0, 0, false, 0);
|
||||
}
|
||||
|
||||
public void remove(IdeFrame frame) {
|
||||
if (!Registry.is("actionSystem.mouseGesturesEnabled")) return;
|
||||
|
||||
|
||||
+16
-3
@@ -19,21 +19,21 @@ import com.intellij.ide.IdeEventQueue;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.actionSystem.DataProvider;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.editor.VisualPosition;
|
||||
import com.intellij.ui.components.Magnificator;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.impl.ApplicationImpl;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.ex.util.EditorUtil;
|
||||
import com.intellij.openapi.ui.Queryable;
|
||||
import com.intellij.openapi.ui.TypingTarget;
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ComponentEvent;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.InputMethodEvent;
|
||||
import java.awt.im.InputContext;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -46,6 +46,19 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP
|
||||
enableInputMethods(true);
|
||||
setFocusCycleRoot(true);
|
||||
setOpaque(true);
|
||||
|
||||
putClientProperty(Magnificator.CLIENT_PROPERTY_KEY, new Magnificator() {
|
||||
@Override
|
||||
public Point magnify(double scale, Point at) {
|
||||
VisualPosition magnificationPosition = myEditor.xyToVisualPosition(at);
|
||||
|
||||
double currentSize = myEditor.getColorsScheme().getEditorFontSize();
|
||||
int defaultFontSize = EditorColorsManager.getInstance().getGlobalScheme().getEditorFontSize();
|
||||
myEditor.setFontSize((int)(double)(int)(Math.max(currentSize * scale, defaultFontSize)));
|
||||
|
||||
return myEditor.visualPositionToXY(magnificationPosition);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public EditorImpl getEditor() {
|
||||
|
||||
Reference in New Issue
Block a user