xiqiu
3 years ago
132 changed files with 8462 additions and 4550 deletions
@ -1,92 +0,0 @@
|
||||
package com.fr.base.svg; |
||||
|
||||
import com.fr.general.IOUtils; |
||||
import org.apache.batik.transcoder.TranscoderException; |
||||
import org.apache.batik.transcoder.TranscoderInput; |
||||
import org.apache.xmlgraphics.java2d.Dimension2DDouble; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.jetbrains.annotations.Nullable; |
||||
|
||||
import java.awt.Image; |
||||
import java.io.IOException; |
||||
import java.net.URL; |
||||
|
||||
/** |
||||
* SVG图标加载器 |
||||
* @author Yvan |
||||
* @version 10.0 |
||||
* Created by Yvan on 2020/12/17 |
||||
*/ |
||||
public class SVGLoader { |
||||
public static final int ICON_DEFAULT_SIZE = 16; |
||||
|
||||
public SVGLoader() { |
||||
} |
||||
|
||||
@Nullable |
||||
public static Image load(@NotNull String url) { |
||||
try { |
||||
URL resource = IOUtils.getResource(url, SVGLoader.class); |
||||
if (resource == null) { |
||||
return null; |
||||
} |
||||
return load(resource, SVGIcon.SYSTEM_SCALE); |
||||
} catch (IOException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@Nullable |
||||
public static Image load(@NotNull URL url) throws IOException { |
||||
return load(url, SVGIcon.SYSTEM_SCALE); |
||||
} |
||||
|
||||
@Nullable |
||||
public static Image load(@NotNull URL url, double scale) throws IOException { |
||||
try { |
||||
String svgUri = url.toString(); |
||||
TranscoderInput input = new TranscoderInput(svgUri); |
||||
return SVGTranscoder.createImage(scale, input).getImage(); |
||||
} catch (TranscoderException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@Nullable |
||||
public static Image load(@NotNull URL url, double scale, Dimension2DDouble dimension) throws IOException { |
||||
try { |
||||
String svgUri = url.toString(); |
||||
TranscoderInput input = new TranscoderInput(svgUri); |
||||
return SVGTranscoder.createImage(scale, input, |
||||
(float) (dimension.getWidth() * scale), (float) (dimension.getHeight() * scale)).getImage(); |
||||
} catch (TranscoderException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
|
||||
@Nullable |
||||
public static Image load(@NotNull URL url, double scale, double overriddenWidth, double overriddenHeight) throws IOException { |
||||
try { |
||||
String svgUri = url.toString(); |
||||
TranscoderInput input = new TranscoderInput(svgUri); |
||||
return SVGTranscoder.createImage(scale, input, (float) (overriddenWidth * scale), (float) (overriddenHeight * scale)).getImage(); |
||||
} catch (TranscoderException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
|
||||
@Nullable |
||||
public static Image load(@NotNull String url, float width, float height) { |
||||
try { |
||||
URL resource = IOUtils.getResource(url, SVGLoader.class); |
||||
if (resource == null) { |
||||
return null; |
||||
} |
||||
TranscoderInput input = new TranscoderInput(resource.toString()); |
||||
return SVGTranscoder.createImage(SVGIcon.SYSTEM_SCALE, input, -1, -1, width, height).getImage(); |
||||
} catch (TranscoderException ignore) { |
||||
return null; |
||||
} |
||||
} |
||||
} |
@ -1,181 +0,0 @@
|
||||
package com.fr.base.svg; |
||||
|
||||
import com.fr.stable.AssistUtils; |
||||
import com.fr.value.AtomicNotNullLazyValue; |
||||
import org.apache.batik.anim.dom.SAXSVGDocumentFactory; |
||||
import org.apache.batik.anim.dom.SVGOMDocument; |
||||
import org.apache.batik.bridge.BridgeContext; |
||||
import org.apache.batik.bridge.UserAgent; |
||||
import org.apache.batik.transcoder.SVGAbstractTranscoder; |
||||
import org.apache.batik.transcoder.TranscoderException; |
||||
import org.apache.batik.transcoder.TranscoderInput; |
||||
import org.apache.batik.transcoder.TranscoderOutput; |
||||
import org.apache.batik.transcoder.image.ImageTranscoder; |
||||
import org.apache.batik.util.XMLResourceDescriptor; |
||||
import org.jetbrains.annotations.NotNull; |
||||
import org.jetbrains.annotations.Nullable; |
||||
import org.w3c.dom.Element; |
||||
import org.w3c.dom.svg.SVGDocument; |
||||
|
||||
import java.awt.GraphicsDevice; |
||||
import java.awt.GraphicsEnvironment; |
||||
import java.awt.Rectangle; |
||||
import java.awt.geom.AffineTransform; |
||||
import java.awt.image.BufferedImage; |
||||
import java.io.IOException; |
||||
import java.io.StringReader; |
||||
|
||||
/** |
||||
* 可以根据某个缩放倍数scale,将SVG图片转化为Image对象 |
||||
* @author Yvan |
||||
* @version 10.0 |
||||
* Created by Yvan on 2020/12/17 |
||||
*/ |
||||
public class SVGTranscoder extends ImageTranscoder { |
||||
|
||||
private static final float DEFAULT_VALUE = -1.0F; |
||||
public static final float ICON_DEFAULT_SIZE = 16F; |
||||
private float origDocWidth; |
||||
private float origDocHeight; |
||||
@Nullable |
||||
private BufferedImage image; |
||||
private final double scale; |
||||
|
||||
@NotNull |
||||
private static AtomicNotNullLazyValue<Double> iconMaxSize = new AtomicNotNullLazyValue<Double>() { |
||||
@NotNull |
||||
@Override |
||||
protected Double compute() { |
||||
double maxSize = Double.MAX_VALUE; |
||||
if (!GraphicsEnvironment.isHeadless()) { |
||||
GraphicsDevice defaultScreenDevice = GraphicsEnvironment |
||||
.getLocalGraphicsEnvironment() |
||||
.getDefaultScreenDevice(); |
||||
Rectangle bounds = defaultScreenDevice.getDefaultConfiguration().getBounds(); |
||||
AffineTransform tx = defaultScreenDevice |
||||
.getDefaultConfiguration() |
||||
.getDefaultTransform(); |
||||
maxSize = Math.max(bounds.width * tx.getScaleX(), bounds.height * tx.getScaleY()); |
||||
} |
||||
return maxSize; |
||||
} |
||||
}; |
||||
|
||||
public SVGTranscoder(double scale) { |
||||
this.scale = scale; |
||||
this.width = ICON_DEFAULT_SIZE; |
||||
this.height = ICON_DEFAULT_SIZE; |
||||
} |
||||
|
||||
public SVGTranscoder(double scale, float width, float height) { |
||||
this.scale = scale; |
||||
this.width = width; |
||||
this.height = height; |
||||
} |
||||
|
||||
public final float getOrigDocWidth() { |
||||
return this.origDocWidth; |
||||
} |
||||
|
||||
public final void setOrigDocWidth(float origDocWidth) { |
||||
this.origDocWidth = origDocWidth; |
||||
} |
||||
|
||||
public final float getOrigDocHeight() { |
||||
return this.origDocHeight; |
||||
} |
||||
|
||||
public final void setOrigDocHeight(float origDocHeight) { |
||||
this.origDocHeight = origDocHeight; |
||||
} |
||||
|
||||
public static double getIconMaxSize() { |
||||
return iconMaxSize.getValue(); |
||||
} |
||||
|
||||
@Nullable |
||||
public final BufferedImage getImage() { |
||||
return this.image; |
||||
} |
||||
|
||||
@NotNull |
||||
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input) throws TranscoderException { |
||||
return createImage(scale, input, -1, -1); |
||||
} |
||||
|
||||
@NotNull |
||||
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight) throws TranscoderException { |
||||
return createImage(scale, input, overriddenWidth, overriddenHeight, ICON_DEFAULT_SIZE, ICON_DEFAULT_SIZE); |
||||
} |
||||
|
||||
@NotNull |
||||
public static SVGTranscoder createImage(double scale, @NotNull TranscoderInput input, float overriddenWidth, float overriddenHeight, float width, float height) throws TranscoderException { |
||||
SVGTranscoder transcoder = new SVGTranscoder(scale, width, height); |
||||
if (!AssistUtils.equals(overriddenWidth, DEFAULT_VALUE)) { |
||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_WIDTH, overriddenWidth); |
||||
} |
||||
|
||||
if (!AssistUtils.equals(overriddenHeight, DEFAULT_VALUE)) { |
||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_HEIGHT, overriddenHeight); |
||||
} |
||||
|
||||
double iconMaxSize = SVGTranscoder.iconMaxSize.getValue(); |
||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_WIDTH, (float) iconMaxSize); |
||||
transcoder.addTranscodingHint(SVGAbstractTranscoder.KEY_MAX_HEIGHT, (float) iconMaxSize); |
||||
transcoder.transcode(input, null); |
||||
return transcoder; |
||||
} |
||||
|
||||
private static SVGDocument createFallbackPlaceholder() { |
||||
try { |
||||
String fallbackIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 16 16\">\n" + |
||||
" <rect x=\"1\" y=\"1\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"red\" stroke-width=\"2\"/>\n" + |
||||
" <line x1=\"1\" y1=\"1\" x2=\"15\" y2=\"15\" stroke=\"red\" stroke-width=\"2\"/>\n" + |
||||
" <line x1=\"1\" y1=\"15\" x2=\"15\" y2=\"1\" stroke=\"red\" stroke-width=\"2\"/>\n" + |
||||
"</svg>\n"; |
||||
|
||||
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(XMLResourceDescriptor.getXMLParserClassName()); |
||||
return (SVGDocument) factory.createDocument(null, new StringReader(fallbackIcon)); |
||||
} catch (IOException e) { |
||||
throw new IllegalStateException(e); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void setImageSize(float docWidth, float docHeight) { |
||||
super.setImageSize((float) (docWidth * this.scale), (float) (docHeight * this.scale)); |
||||
this.origDocWidth = docWidth; |
||||
this.origDocHeight = docHeight; |
||||
} |
||||
|
||||
@Override |
||||
@NotNull |
||||
public BufferedImage createImage(int width, int height) { |
||||
return new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); |
||||
} |
||||
|
||||
@Override |
||||
public void writeImage(@NotNull BufferedImage image, @Nullable TranscoderOutput output) { |
||||
this.image = image; |
||||
} |
||||
|
||||
@Override |
||||
@NotNull |
||||
protected UserAgent createUserAgent() { |
||||
return new SVGAbstractTranscoderUserAgent() { |
||||
@Override |
||||
@NotNull |
||||
public SVGDocument getBrokenLinkDocument(@NotNull Element e, @NotNull String url, @NotNull String message) { |
||||
return createFallbackPlaceholder(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/** |
||||
* 开放访问权限 |
||||
*/ |
||||
@Override |
||||
public BridgeContext createBridgeContext(SVGOMDocument doc) { |
||||
return super.createBridgeContext(doc); |
||||
} |
||||
} |
@ -1,101 +0,0 @@
|
||||
package com.fr.base.svg; |
||||
|
||||
import com.bulenkov.iconloader.util.UIUtil; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StableUtils; |
||||
import com.fr.stable.os.OperatingSystem; |
||||
import org.jetbrains.annotations.NotNull; |
||||
|
||||
import java.awt.GraphicsConfiguration; |
||||
import java.awt.GraphicsDevice; |
||||
import java.awt.GraphicsEnvironment; |
||||
import java.lang.reflect.Method; |
||||
import java.util.concurrent.atomic.AtomicReference; |
||||
|
||||
/** |
||||
* 获取系统Scale相关的工具类 |
||||
* @author Yvan |
||||
* @version 10.0 |
||||
* Created by Yvan on 2020/12/17 |
||||
*/ |
||||
public class SystemScaleUtils { |
||||
|
||||
private static final AtomicReference<Boolean> JRE_HIDPI = new AtomicReference<>(); |
||||
|
||||
private static final String HI_DPI = "hidpi"; |
||||
|
||||
/** |
||||
* 判断是否支持高清 |
||||
* @return |
||||
*/ |
||||
public static boolean isJreHiDPIEnabled() { |
||||
if (JRE_HIDPI.get() != null) { |
||||
return JRE_HIDPI.get(); |
||||
} |
||||
if (OperatingSystem.isMacos()) { |
||||
// 如果是mac os系统,直接返回true
|
||||
return true; |
||||
} |
||||
if (OperatingSystem.isWindows() && StableUtils.getMajorJavaVersion() <= 8) { |
||||
// 如果是jdk8 + Windows系统,直接返回false
|
||||
return false; |
||||
} |
||||
synchronized (JRE_HIDPI) { |
||||
if (JRE_HIDPI.get() != null) { |
||||
return JRE_HIDPI.get(); |
||||
} |
||||
boolean result = false; |
||||
if (getBooleanProperty(HI_DPI, true)) { |
||||
try { |
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); |
||||
Class<?> sunGraphicsEnvironmentClass = Class.forName("sun.java2d.SunGraphicsEnvironment"); |
||||
if (sunGraphicsEnvironmentClass.isInstance(ge)) { |
||||
try { |
||||
Method method = sunGraphicsEnvironmentClass.getDeclaredMethod("isUIScaleEnabled"); |
||||
method.setAccessible(true); |
||||
result = (Boolean)method.invoke(ge); |
||||
} |
||||
catch (NoSuchMethodException e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage()); |
||||
} |
||||
} |
||||
} |
||||
catch (Throwable ignore) { |
||||
} |
||||
} |
||||
JRE_HIDPI.set(result); |
||||
return result; |
||||
} |
||||
} |
||||
|
||||
public static boolean getBooleanProperty(@NotNull final String key, final boolean defaultValue) { |
||||
final String value = System.getProperty(key); |
||||
return value == null ? defaultValue : Boolean.parseBoolean(value); |
||||
} |
||||
|
||||
/** |
||||
* 获取系统Scale |
||||
* @return |
||||
*/ |
||||
public static float sysScale() { |
||||
// 如果检测到是retina,直接返回2
|
||||
if (UIUtil.isRetina()) { |
||||
return 2.0f; |
||||
} |
||||
float scale = 1.0f; |
||||
// 先判断是否支持高清,不支持代表此时是Windows + jdk8 的设计器,返回的scale值为1.0
|
||||
if (isJreHiDPIEnabled()) { |
||||
// 获取屏幕图形设备对象
|
||||
GraphicsDevice graphicsDevice = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); |
||||
if (graphicsDevice != null) { |
||||
// 获取图形配置对象
|
||||
GraphicsConfiguration configuration = graphicsDevice.getDefaultConfiguration(); |
||||
if (configuration != null && configuration.getDevice().getType() != GraphicsDevice.TYPE_PRINTER) { |
||||
// 获取屏幕缩放率,Windows+jdk11环境下会得到用户设置的dpi值
|
||||
scale = (float) configuration.getDefaultTransform().getScaleX(); |
||||
} |
||||
} |
||||
} |
||||
return scale; |
||||
} |
||||
} |
@ -0,0 +1,5 @@
|
||||
package com.fr.design.gui.autocomplete; |
||||
|
||||
public interface AutoCompleteExtraRefreshComponent { |
||||
void refresh(String replacementText); |
||||
} |
@ -0,0 +1,982 @@
|
||||
package com.fr.design.gui.autocomplete; |
||||
|
||||
import com.fr.design.gui.syntax.ui.rsyntaxtextarea.PopupWindowDecorator; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.ComponentOrientation; |
||||
import java.awt.Dimension; |
||||
import java.awt.Point; |
||||
import java.awt.Rectangle; |
||||
import java.awt.Toolkit; |
||||
import java.awt.Window; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseListener; |
||||
import java.util.List; |
||||
import javax.swing.AbstractAction; |
||||
import javax.swing.Action; |
||||
import javax.swing.ActionMap; |
||||
import javax.swing.InputMap; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JList; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JScrollPane; |
||||
import javax.swing.JWindow; |
||||
import javax.swing.KeyStroke; |
||||
import javax.swing.ListCellRenderer; |
||||
import javax.swing.SwingUtilities; |
||||
import javax.swing.event.CaretEvent; |
||||
import javax.swing.event.CaretListener; |
||||
import javax.swing.event.ListSelectionEvent; |
||||
import javax.swing.event.ListSelectionListener; |
||||
import javax.swing.plaf.ListUI; |
||||
import javax.swing.text.Caret; |
||||
import javax.swing.text.JTextComponent; |
||||
|
||||
public abstract class AutoCompleteWithExtraRefreshPopupWindow extends JWindow implements CaretListener, |
||||
ListSelectionListener, MouseListener { |
||||
private final static int DIS = 5; |
||||
/** |
||||
* The parent AutoCompletion instance. |
||||
*/ |
||||
private AutoCompletion ac; |
||||
|
||||
/** |
||||
* The list of completion choices. |
||||
*/ |
||||
private JList list; |
||||
|
||||
/** |
||||
* The contents of {@link #list()}. |
||||
*/ |
||||
private CompletionListModel model; |
||||
|
||||
/** |
||||
* A hack to work around the fact that we clear our completion model (and |
||||
* our selection) when hiding the completion window. This allows us to |
||||
* still know what the user selected after the popup is hidden. |
||||
*/ |
||||
private Completion lastSelection; |
||||
|
||||
/** |
||||
* Optional popup window containing a description of the currently |
||||
* selected completion. |
||||
*/ |
||||
private AutoCompleteDescWindow descWindow; |
||||
|
||||
/** |
||||
* The preferred size of the optional description window. This field |
||||
* only exists because the user may (and usually will) set the size of |
||||
* the description window before it exists (it must be parented to a |
||||
* Window). |
||||
*/ |
||||
private Dimension preferredDescWindowSize; |
||||
|
||||
|
||||
|
||||
/** |
||||
* Whether the completion window and the optional description window |
||||
* should be displayed above the current caret position (as opposed to |
||||
* underneath it, which is preferred unless there is not enough space). |
||||
*/ |
||||
private boolean aboveCaret; |
||||
|
||||
private int lastLine; |
||||
|
||||
private KeyActionPair escapeKap; |
||||
private KeyActionPair upKap; |
||||
private KeyActionPair downKap; |
||||
private KeyActionPair leftKap; |
||||
private KeyActionPair rightKap; |
||||
private KeyActionPair enterKap; |
||||
private KeyActionPair tabKap; |
||||
private KeyActionPair homeKap; |
||||
private KeyActionPair endKap; |
||||
private KeyActionPair pageUpKap; |
||||
private KeyActionPair pageDownKap; |
||||
private KeyActionPair ctrlCKap; |
||||
|
||||
private KeyActionPair oldEscape, oldUp, oldDown, oldLeft, oldRight, |
||||
oldEnter, oldTab, oldHome, oldEnd, oldPageUp, oldPageDown, |
||||
oldCtrlC; |
||||
|
||||
/** |
||||
* The space between the caret and the completion popup. |
||||
*/ |
||||
private static final int VERTICAL_SPACE = 1; |
||||
|
||||
/** |
||||
* The class name of the Substance List UI. |
||||
*/ |
||||
private static final String SUBSTANCE_LIST_UI = |
||||
"org.pushingpixels.substance.internal.ui.SubstanceListUI"; |
||||
|
||||
|
||||
protected AutoCompleteExtraRefreshComponent component; |
||||
|
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param parent The parent window (hosting the text component). |
||||
* @param ac The auto-completion instance. |
||||
*/ |
||||
public AutoCompleteWithExtraRefreshPopupWindow(Window parent, final AutoCompletion ac) { |
||||
|
||||
super(parent); |
||||
ComponentOrientation o = ac.getTextComponentOrientation(); |
||||
|
||||
this.ac = ac; |
||||
model = new CompletionListModel(); |
||||
list = new PopupList(model); |
||||
|
||||
list.setCellRenderer(new DelegatingCellRenderer()); |
||||
list.addListSelectionListener(this); |
||||
list.addMouseListener(this); |
||||
|
||||
JPanel contentPane = new JPanel(new BorderLayout()); |
||||
JScrollPane sp = new JScrollPane(list, |
||||
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, |
||||
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); |
||||
|
||||
// In 1.4, JScrollPane.setCorner() has a bug where it won't accept
|
||||
// JScrollPane.LOWER_TRAILING_CORNER, even though that constant is
|
||||
// defined. So we have to put the logic added in 1.5 to handle it
|
||||
// here.
|
||||
JPanel corner = new SizeGrip(); |
||||
//sp.setCorner(JScrollPane.LOWER_TRAILING_CORNER, corner);
|
||||
boolean isLeftToRight = o.isLeftToRight(); |
||||
String str = isLeftToRight ? JScrollPane.LOWER_RIGHT_CORNER : |
||||
JScrollPane.LOWER_LEFT_CORNER; |
||||
sp.setCorner(str, corner); |
||||
|
||||
contentPane.add(sp); |
||||
setContentPane(contentPane); |
||||
applyComponentOrientation(o); |
||||
|
||||
// Give apps a chance to decorate us with drop shadows, etc.
|
||||
if (Util.getShouldAllowDecoratingMainAutoCompleteWindows()) { |
||||
PopupWindowDecorator decorator = PopupWindowDecorator.get(); |
||||
if (decorator != null) { |
||||
decorator.decorate(this); |
||||
} |
||||
} |
||||
|
||||
pack(); |
||||
|
||||
setFocusableWindowState(false); |
||||
|
||||
lastLine = -1; |
||||
|
||||
} |
||||
|
||||
|
||||
public void caretUpdate(CaretEvent e) { |
||||
if (isVisible()) { // Should always be true
|
||||
int line = ac.getLineOfCaret(); |
||||
if (line != lastLine) { |
||||
lastLine = -1; |
||||
setVisible(false); |
||||
} else { |
||||
doAutocomplete(); |
||||
} |
||||
} else if (AutoCompletion.isDebug()) { |
||||
Thread.dumpStack(); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Creates the description window. |
||||
* |
||||
* @return The description window. |
||||
*/ |
||||
private AutoCompleteDescWindow createDescriptionWindow() { |
||||
AutoCompleteDescWindow dw = new AutoCompleteDescWindow(this, ac); |
||||
dw.applyComponentOrientation(ac.getTextComponentOrientation()); |
||||
Dimension size = preferredDescWindowSize; |
||||
if (size == null) { |
||||
size = getSize(); |
||||
} |
||||
dw.setSize(size); |
||||
return dw; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Creates the mappings from keys to Actions we'll be putting into the |
||||
* text component's ActionMap and InputMap. |
||||
*/ |
||||
private void createKeyActionPairs() { |
||||
|
||||
// Actions we'll install.
|
||||
EnterAction enterAction = new EnterAction(); |
||||
escapeKap = new KeyActionPair("Escape", new EscapeAction()); |
||||
upKap = new KeyActionPair("Up", new UpAction()); |
||||
downKap = new KeyActionPair("Down", new DownAction()); |
||||
leftKap = new KeyActionPair("Left", new LeftAction()); |
||||
rightKap = new KeyActionPair("Right", new RightAction()); |
||||
enterKap = new KeyActionPair("Enter", enterAction); |
||||
tabKap = new KeyActionPair("Tab", enterAction); |
||||
homeKap = new KeyActionPair("Home", new HomeAction()); |
||||
endKap = new KeyActionPair("End", new EndAction()); |
||||
pageUpKap = new KeyActionPair("PageUp", new PageUpAction()); |
||||
pageDownKap = new KeyActionPair("PageDown", new PageDownAction()); |
||||
ctrlCKap = new KeyActionPair("CtrlC", new CopyAction()); |
||||
|
||||
// Buffers for the actions we replace.
|
||||
oldEscape = new KeyActionPair(); |
||||
oldUp = new KeyActionPair(); |
||||
oldDown = new KeyActionPair(); |
||||
oldLeft = new KeyActionPair(); |
||||
oldRight = new KeyActionPair(); |
||||
oldEnter = new KeyActionPair(); |
||||
oldTab = new KeyActionPair(); |
||||
oldHome = new KeyActionPair(); |
||||
oldEnd = new KeyActionPair(); |
||||
oldPageUp = new KeyActionPair(); |
||||
oldPageDown = new KeyActionPair(); |
||||
oldCtrlC = new KeyActionPair(); |
||||
|
||||
} |
||||
|
||||
|
||||
protected void doAutocomplete() { |
||||
lastLine = ac.refreshPopupWindow(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the copy keystroke to use for this platform. |
||||
* |
||||
* @return The copy keystroke. |
||||
*/ |
||||
private static final KeyStroke getCopyKeyStroke() { |
||||
int key = KeyEvent.VK_C; |
||||
int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); |
||||
return KeyStroke.getKeyStroke(key, mask); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the default list cell renderer used when a completion provider |
||||
* does not supply its own. |
||||
* |
||||
* @return The default list cell renderer. |
||||
* @see #setListCellRenderer(ListCellRenderer) |
||||
*/ |
||||
public ListCellRenderer getListCellRenderer() { |
||||
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. |
||||
getCellRenderer(); |
||||
return dcr.getFallbackCellRenderer(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Returns the selected value, or <code>null</code> if nothing is selected. |
||||
* |
||||
* @return The selected value. |
||||
*/ |
||||
public Completion getSelection() { |
||||
return isShowing() ? (Completion) list.getSelectedValue() : lastSelection; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Inserts the currently selected completion. |
||||
* |
||||
* @see #getSelection() |
||||
*/ |
||||
private void insertSelectedCompletion() { |
||||
Completion comp = getSelection(); |
||||
ac.insertCompletion(comp); |
||||
} |
||||
|
||||
public void installComp(AutoCompleteExtraRefreshComponent component){ |
||||
this.component = component; |
||||
} |
||||
|
||||
public void refreshInstallComp() { |
||||
component.refresh(getSelection().getReplacementText()); |
||||
} |
||||
|
||||
/** |
||||
* Registers keyboard actions to listen for in the text component and |
||||
* intercept. |
||||
* |
||||
* @see #uninstallKeyBindings() |
||||
*/ |
||||
private void installKeyBindings() { |
||||
|
||||
if (AutoCompletion.isDebug()) { |
||||
FineLoggerFactory.getLogger().debug("PopupWindow: Installing keybindings"); |
||||
} |
||||
|
||||
if (escapeKap == null) { // Lazily create actions.
|
||||
createKeyActionPairs(); |
||||
} |
||||
|
||||
JTextComponent comp = ac.getTextComponent(); |
||||
InputMap im = comp.getInputMap(); |
||||
ActionMap am = comp.getActionMap(); |
||||
|
||||
replaceAction(im, am, KeyEvent.VK_ESCAPE, escapeKap, oldEscape); |
||||
if (AutoCompletion.isDebug() && oldEscape.action == escapeKap.action) { |
||||
Thread.dumpStack(); |
||||
} |
||||
replaceAction(im, am, KeyEvent.VK_UP, upKap, oldUp); |
||||
replaceAction(im, am, KeyEvent.VK_LEFT, leftKap, oldLeft); |
||||
replaceAction(im, am, KeyEvent.VK_DOWN, downKap, oldDown); |
||||
replaceAction(im, am, KeyEvent.VK_RIGHT, rightKap, oldRight); |
||||
replaceAction(im, am, KeyEvent.VK_ENTER, enterKap, oldEnter); |
||||
replaceAction(im, am, KeyEvent.VK_TAB, tabKap, oldTab); |
||||
replaceAction(im, am, KeyEvent.VK_HOME, homeKap, oldHome); |
||||
replaceAction(im, am, KeyEvent.VK_END, endKap, oldEnd); |
||||
replaceAction(im, am, KeyEvent.VK_PAGE_UP, pageUpKap, oldPageUp); |
||||
replaceAction(im, am, KeyEvent.VK_PAGE_DOWN, pageDownKap, oldPageDown); |
||||
|
||||
// Make Ctrl+C copy from description window. This isn't done
|
||||
// automagically because the desc. window is not focusable, and copying
|
||||
// from text components can only be done from focused components.
|
||||
KeyStroke ks = getCopyKeyStroke(); |
||||
oldCtrlC.key = im.get(ks); |
||||
im.put(ks, ctrlCKap.key); |
||||
oldCtrlC.action = am.get(ctrlCKap.key); |
||||
am.put(ctrlCKap.key, ctrlCKap.action); |
||||
|
||||
comp.addCaretListener(this); |
||||
|
||||
} |
||||
|
||||
|
||||
public void mouseClicked(MouseEvent e) { |
||||
if (e.getClickCount() == 2 && e.getButton() == 1) { |
||||
insertSelectedCompletion(); |
||||
} |
||||
} |
||||
|
||||
|
||||
public void mouseEntered(MouseEvent e) { |
||||
} |
||||
|
||||
|
||||
public void mouseExited(MouseEvent e) { |
||||
} |
||||
|
||||
|
||||
public void mousePressed(MouseEvent e) { |
||||
refreshInstallComp(); |
||||
} |
||||
|
||||
|
||||
public void mouseReleased(MouseEvent e) { |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Positions the description window relative to the completion choices |
||||
* window. We assume there is room on one side of the other for this |
||||
* entire window to fit. |
||||
*/ |
||||
private void positionDescWindow() { |
||||
|
||||
boolean showDescWindow = descWindow != null && ac.isShowDescWindow(); |
||||
if (!showDescWindow) { |
||||
return; |
||||
} |
||||
|
||||
// Don't use getLocationOnScreen() as this throws an exception if
|
||||
// window isn't visible yet, but getLocation() doesn't, and is in
|
||||
// screen coordinates!
|
||||
Point p = getLocation(); |
||||
Rectangle screenBounds = Util.getScreenBoundsForPoint(p.x, p.y); |
||||
//Dimension screenSize = getToolkit().getScreenSize();
|
||||
//int totalH = Math.max(getHeight(), descWindow.getHeight());
|
||||
|
||||
// Try to position to the right first (LTR)
|
||||
int x; |
||||
if (ac.getTextComponentOrientation().isLeftToRight()) { |
||||
x = getX() + getWidth() + DIS; |
||||
if (x + descWindow.getWidth() > screenBounds.x + screenBounds.width) { // doesn't fit
|
||||
x = getX() - DIS - descWindow.getWidth(); |
||||
} |
||||
} else { // RTL
|
||||
x = getX() - DIS - descWindow.getWidth(); |
||||
if (x < screenBounds.x) { // Doesn't fit
|
||||
x = getX() + getWidth() + DIS; |
||||
} |
||||
} |
||||
|
||||
int y = getY(); |
||||
if (aboveCaret) { |
||||
y = y + getHeight() - descWindow.getHeight(); |
||||
} |
||||
|
||||
if (x != descWindow.getX() || y != descWindow.getY()) { |
||||
descWindow.setLocation(x, y); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* "Puts back" the original key/Action pair for a keystroke. This is used |
||||
* when this popup is hidden. |
||||
* |
||||
* @param im The input map. |
||||
* @param am The action map. |
||||
* @param key The keystroke whose key/Action pair to change. |
||||
* @param kap The (original) key/Action pair. |
||||
* @see #replaceAction(InputMap, ActionMap, int, KeyActionPair, KeyActionPair) |
||||
*/ |
||||
private void putBackAction(InputMap im, ActionMap am, int key, |
||||
KeyActionPair kap) { |
||||
KeyStroke ks = KeyStroke.getKeyStroke(key, 0); |
||||
am.put(im.get(ks), kap.action); // Original action for the "new" key
|
||||
im.put(ks, kap.key); // Original key for the keystroke.
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Replaces a key/Action pair in an InputMap and ActionMap with a new |
||||
* pair. |
||||
* |
||||
* @param im The input map. |
||||
* @param am The action map. |
||||
* @param key The keystroke whose information to replace. |
||||
* @param kap The new key/Action pair for <code>key</code>. |
||||
* @param old A buffer in which to place the old key/Action pair. |
||||
* @see #putBackAction(InputMap, ActionMap, int, KeyActionPair) |
||||
*/ |
||||
private void replaceAction(InputMap im, ActionMap am, int key, |
||||
KeyActionPair kap, KeyActionPair old) { |
||||
KeyStroke ks = KeyStroke.getKeyStroke(key, 0); |
||||
old.key = im.get(ks); |
||||
im.put(ks, kap.key); |
||||
old.action = am.get(kap.key); |
||||
am.put(kap.key, kap.action); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Selects the first item in the completion list. |
||||
* |
||||
* @see #selectLastItem() |
||||
*/ |
||||
private void selectFirstItem() { |
||||
if (model.getSize() > 0) { |
||||
list.setSelectedIndex(0); |
||||
list.ensureIndexIsVisible(0); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Selects the last item in the completion list. |
||||
* |
||||
* @see #selectFirstItem() |
||||
*/ |
||||
private void selectLastItem() { |
||||
int index = model.getSize() - 1; |
||||
if (index > -1) { |
||||
list.setSelectedIndex(index); |
||||
list.ensureIndexIsVisible(index); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Selects the next item in the completion list. |
||||
* |
||||
* @see #selectPreviousItem() |
||||
*/ |
||||
private void selectNextItem() { |
||||
int index = list.getSelectedIndex(); |
||||
if (index > -1) { |
||||
index = (index + 1) % model.getSize(); |
||||
list.setSelectedIndex(index); |
||||
list.ensureIndexIsVisible(index); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Selects the completion item one "page down" from the currently selected |
||||
* one. |
||||
* |
||||
* @see #selectPageUpItem() |
||||
*/ |
||||
private void selectPageDownItem() { |
||||
int visibleRowCount = list.getVisibleRowCount(); |
||||
int i = Math.min(list.getModel().getSize() - 1, |
||||
list.getSelectedIndex() + visibleRowCount); |
||||
list.setSelectedIndex(i); |
||||
list.ensureIndexIsVisible(i); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Selects the completion item one "page up" from the currently selected |
||||
* one. |
||||
* |
||||
* @see #selectPageDownItem() |
||||
*/ |
||||
private void selectPageUpItem() { |
||||
int visibleRowCount = list.getVisibleRowCount(); |
||||
int i = Math.max(0, list.getSelectedIndex() - visibleRowCount); |
||||
list.setSelectedIndex(i); |
||||
list.ensureIndexIsVisible(i); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Selects the previous item in the completion list. |
||||
* |
||||
* @see #selectNextItem() |
||||
*/ |
||||
private void selectPreviousItem() { |
||||
int index = list.getSelectedIndex(); |
||||
switch (index) { |
||||
case 0: |
||||
index = list.getModel().getSize() - 1; |
||||
break; |
||||
case -1: // Check for an empty list (would be an error)
|
||||
index = list.getModel().getSize() - 1; |
||||
if (index == -1) { |
||||
return; |
||||
} |
||||
break; |
||||
default: |
||||
index = index - 1; |
||||
break; |
||||
} |
||||
list.setSelectedIndex(index); |
||||
list.ensureIndexIsVisible(index); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets the completions to display in the choices list. The first |
||||
* completion is selected. |
||||
* |
||||
* @param completions The completions to display. |
||||
*/ |
||||
public void setCompletions(List<Completion> completions) { |
||||
model.setContents(completions); |
||||
selectFirstItem(); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets the size of the description window. |
||||
* |
||||
* @param size The new size. This cannot be <code>null</code>. |
||||
*/ |
||||
public void setDescriptionWindowSize(Dimension size) { |
||||
if (descWindow != null) { |
||||
descWindow.setSize(size); |
||||
} else { |
||||
preferredDescWindowSize = size; |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets the default list cell renderer to use when a completion provider |
||||
* does not supply its own. |
||||
* |
||||
* @param renderer The renderer to use. If this is <code>null</code>, |
||||
* a default renderer is used. |
||||
* @see #getListCellRenderer() |
||||
*/ |
||||
public void setListCellRenderer(ListCellRenderer renderer) { |
||||
DelegatingCellRenderer dcr = (DelegatingCellRenderer) list. |
||||
getCellRenderer(); |
||||
dcr.setFallbackCellRenderer(renderer); |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Sets the location of this window to be "good" relative to the specified |
||||
* rectangle. That rectangle should be the location of the text |
||||
* component's caret, in screen coordinates. |
||||
* |
||||
* @param r The text component's caret position, in screen coordinates. |
||||
*/ |
||||
public void setLocationRelativeTo(Rectangle r) { |
||||
|
||||
// Multi-monitor support - make sure the completion window (and
|
||||
// description window, if applicable) both fit in the same window in
|
||||
// a multi-monitor environment. To do this, we decide which monitor
|
||||
// the rectangle "r" is in, and use that one (just pick top-left corner
|
||||
// as the defining point).
|
||||
Rectangle screenBounds = Util.getScreenBoundsForPoint(r.x, r.y); |
||||
//Dimension screenSize = getToolkit().getScreenSize();
|
||||
|
||||
boolean showDescWindow = descWindow != null && ac.isShowDescWindow(); |
||||
int totalH = getHeight(); |
||||
if (showDescWindow) { |
||||
totalH = Math.max(totalH, descWindow.getHeight()); |
||||
} |
||||
|
||||
// Try putting our stuff "below" the caret first. We assume that the
|
||||
// entire height of our stuff fits on the screen one way or the other.
|
||||
aboveCaret = false; |
||||
int y = r.y + r.height + VERTICAL_SPACE; |
||||
if (y + totalH > screenBounds.height) { |
||||
y = r.y - VERTICAL_SPACE - getHeight(); |
||||
aboveCaret = true; |
||||
} |
||||
|
||||
// Get x-coordinate of completions. Try to align left edge with the
|
||||
// caret first.
|
||||
int x = r.x; |
||||
if (!ac.getTextComponentOrientation().isLeftToRight()) { |
||||
x -= getWidth(); // RTL => align right edge
|
||||
} |
||||
if (x < screenBounds.x) { |
||||
x = screenBounds.x; |
||||
} else if (x + getWidth() > screenBounds.x + screenBounds.width) { // completions don't fit
|
||||
x = screenBounds.x + screenBounds.width - getWidth(); |
||||
} |
||||
|
||||
setLocation(x, y); |
||||
|
||||
// Position the description window, if necessary.
|
||||
if (showDescWindow) { |
||||
positionDescWindow(); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Toggles the visibility of this popup window. |
||||
* |
||||
* @param visible Whether this window should be visible. |
||||
*/ |
||||
@Override |
||||
public void setVisible(boolean visible) { |
||||
|
||||
if (visible != isVisible()) { |
||||
|
||||
if (visible) { |
||||
installKeyBindings(); |
||||
lastLine = ac.getLineOfCaret(); |
||||
selectFirstItem(); |
||||
if (descWindow == null && ac.isShowDescWindow()) { |
||||
descWindow = createDescriptionWindow(); |
||||
positionDescWindow(); |
||||
} |
||||
// descWindow needs a kick-start the first time it's displayed.
|
||||
// Also, the newly-selected item in the choices list is
|
||||
// probably different from the previous one anyway.
|
||||
if (descWindow != null) { |
||||
Completion c = (Completion) list.getSelectedValue(); |
||||
if (c != null) { |
||||
descWindow.setDescriptionFor(c); |
||||
} |
||||
} |
||||
} else { |
||||
uninstallKeyBindings(); |
||||
} |
||||
|
||||
super.setVisible(visible); |
||||
|
||||
// Some languages, such as Java, can use quite a lot of memory
|
||||
// when displaying hundreds of completion choices. We pro-actively
|
||||
// clear our list model here to make them available for GC.
|
||||
// Otherwise, they stick around, and consider the following: a
|
||||
// user starts code-completion for Java 5 SDK classes, then hides
|
||||
// the dialog, then changes the "class path" to use a Java 6 SDK
|
||||
// instead. On pressing Ctrl+space, a new array of Completions is
|
||||
// created. If this window holds on to the previous Completions,
|
||||
// you're getting roughly 2x the necessary Completions in memory
|
||||
// until the Completions are actually passed to this window.
|
||||
if (!visible) { // Do after super.setVisible(false)
|
||||
lastSelection = (Completion) list.getSelectedValue(); |
||||
model.clear(); |
||||
} |
||||
|
||||
// Must set descWindow's visibility one way or the other each time,
|
||||
// because of the way child JWindows' visibility is handled - in
|
||||
// some ways it's dependent on the parent, in other ways it's not.
|
||||
if (descWindow != null) { |
||||
descWindow.setVisible(visible && ac.isShowDescWindow()); |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Stops intercepting certain keystrokes from the text component. |
||||
* |
||||
* @see #installKeyBindings() |
||||
*/ |
||||
private void uninstallKeyBindings() { |
||||
|
||||
if (AutoCompletion.isDebug()) { |
||||
FineLoggerFactory.getLogger().debug("PopupWindow: Removing keybindings"); |
||||
} |
||||
|
||||
JTextComponent comp = ac.getTextComponent(); |
||||
InputMap im = comp.getInputMap(); |
||||
ActionMap am = comp.getActionMap(); |
||||
|
||||
putBackAction(im, am, KeyEvent.VK_ESCAPE, oldEscape); |
||||
putBackAction(im, am, KeyEvent.VK_UP, oldUp); |
||||
putBackAction(im, am, KeyEvent.VK_DOWN, oldDown); |
||||
putBackAction(im, am, KeyEvent.VK_LEFT, oldLeft); |
||||
putBackAction(im, am, KeyEvent.VK_RIGHT, oldRight); |
||||
putBackAction(im, am, KeyEvent.VK_ENTER, oldEnter); |
||||
putBackAction(im, am, KeyEvent.VK_TAB, oldTab); |
||||
putBackAction(im, am, KeyEvent.VK_HOME, oldHome); |
||||
putBackAction(im, am, KeyEvent.VK_END, oldEnd); |
||||
putBackAction(im, am, KeyEvent.VK_PAGE_UP, oldPageUp); |
||||
putBackAction(im, am, KeyEvent.VK_PAGE_DOWN, oldPageDown); |
||||
|
||||
// Ctrl+C
|
||||
KeyStroke ks = getCopyKeyStroke(); |
||||
am.put(im.get(ks), oldCtrlC.action); // Original action
|
||||
im.put(ks, oldCtrlC.key); // Original key
|
||||
|
||||
comp.removeCaretListener(this); |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* Updates the <tt>LookAndFeel</tt> of this window and the description |
||||
* window. |
||||
*/ |
||||
public void updateUI() { |
||||
SwingUtilities.updateComponentTreeUI(this); |
||||
if (descWindow != null) { |
||||
descWindow.updateUI(); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Called when a new item is selected in the popup list. |
||||
* |
||||
* @param e The event. |
||||
*/ |
||||
public void valueChanged(ListSelectionEvent e) { |
||||
if (!e.getValueIsAdjusting()) { |
||||
Object value = list.getSelectedValue(); |
||||
if (value != null && descWindow != null) { |
||||
descWindow.setDescriptionFor((Completion) value); |
||||
positionDescWindow(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
class CopyAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
boolean doNormalCopy = false; |
||||
if (descWindow != null && descWindow.isVisible()) { |
||||
doNormalCopy = !descWindow.copy(); |
||||
} |
||||
if (doNormalCopy) { |
||||
ac.getTextComponent().copy(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class DownAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
selectNextItem(); |
||||
refreshInstallComp(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class EndAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
selectLastItem(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class EnterAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
insertSelectedCompletion(); |
||||
refreshInstallComp(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class EscapeAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
setVisible(false); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class HomeAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
selectFirstItem(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* A mapping from a key (an Object) to an Action. |
||||
*/ |
||||
private static class KeyActionPair { |
||||
|
||||
public Object key; |
||||
public Action action; |
||||
|
||||
public KeyActionPair() { |
||||
} |
||||
|
||||
public KeyActionPair(Object key, Action a) { |
||||
this.key = key; |
||||
this.action = a; |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class LeftAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
JTextComponent comp = ac.getTextComponent(); |
||||
Caret c = comp.getCaret(); |
||||
int dot = c.getDot(); |
||||
if (dot > 0) { |
||||
c.setDot(--dot); |
||||
// Ensure moving left hasn't moved us up a line, thus
|
||||
// hiding the popup window.
|
||||
if (comp.isVisible()) { |
||||
if (lastLine != -1) { |
||||
doAutocomplete(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class PageDownAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
selectPageDownItem(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class PageUpAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
selectPageUpItem(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
/** |
||||
* The actual list of completion choices in this popup window. |
||||
*/ |
||||
private class PopupList extends JList { |
||||
|
||||
public PopupList(CompletionListModel model) { |
||||
super(model); |
||||
} |
||||
|
||||
@Override |
||||
public void setUI(ListUI ui) { |
||||
if (Util.getUseSubstanceRenderers() && |
||||
SUBSTANCE_LIST_UI.equals(ui.getClass().getName())) { |
||||
// Substance requires its special ListUI be installed for
|
||||
// its renderers to actually render (!), but long completion
|
||||
// lists (e.g. PHPCompletionProvider in RSTALanguageSupport)
|
||||
// will simply populate too slowly on initial display (when
|
||||
// calculating preferred size of all items), so in this case
|
||||
// we give a prototype cell value.
|
||||
CompletionProvider p = ac.getCompletionProvider(); |
||||
BasicCompletion bc = new BasicCompletion(p, "Hello world"); |
||||
setPrototypeCellValue(bc); |
||||
} else { |
||||
// Our custom UI that is faster for long HTML completion lists.
|
||||
ui = new FastListUI(); |
||||
setPrototypeCellValue(null); |
||||
} |
||||
super.setUI(ui); |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class RightAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
JTextComponent comp = ac.getTextComponent(); |
||||
Caret c = comp.getCaret(); |
||||
int dot = c.getDot(); |
||||
if (dot < comp.getDocument().getLength()) { |
||||
c.setDot(++dot); |
||||
// Ensure moving right hasn't moved us up a line, thus
|
||||
// hiding the popup window.
|
||||
if (comp.isVisible()) { |
||||
if (lastLine != -1) { |
||||
doAutocomplete(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
|
||||
class UpAction extends AbstractAction { |
||||
|
||||
public void actionPerformed(ActionEvent e) { |
||||
if (isVisible()) { |
||||
selectPreviousItem(); |
||||
refreshInstallComp(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,16 @@
|
||||
package com.fr.design.gui.autocomplete; |
||||
|
||||
import java.awt.Window; |
||||
|
||||
public class JSAutoCompletePopupWindow extends AutoCompleteWithExtraRefreshPopupWindow { |
||||
|
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param parent The parent window (hosting the text component). |
||||
* @param ac The auto-completion instance. |
||||
*/ |
||||
public JSAutoCompletePopupWindow(Window parent, AutoCompletion ac) { |
||||
super(parent, ac); |
||||
} |
||||
} |
@ -0,0 +1,31 @@
|
||||
package com.fr.design.gui.autocomplete; |
||||
|
||||
public class JSImplPaneAutoCompletion extends AutoCompletionWithExtraRefresh{ |
||||
/** |
||||
* Constructor. |
||||
* |
||||
* @param provider The completion provider. This cannot be |
||||
* <code>null</code>. |
||||
*/ |
||||
public JSImplPaneAutoCompletion(CompletionProvider provider) { |
||||
super(provider); |
||||
} |
||||
|
||||
@Override |
||||
protected AutoCompleteWithExtraRefreshPopupWindow createAutoCompletePopupWindow() { |
||||
JSAutoCompletePopupWindow popupWindow = new JSAutoCompletePopupWindow(getParentWindow(),this); |
||||
popupWindow.applyComponentOrientation( |
||||
getTextComponentOrientation()); |
||||
if (getCellRender() != null) { |
||||
popupWindow.setListCellRenderer(getCellRender()); |
||||
} |
||||
if (getPreferredChoicesWindowSize() != null) { |
||||
popupWindow.setSize(getPreferredChoicesWindowSize()); |
||||
} |
||||
if (getPreferredDescWindowSize() != null) { |
||||
popupWindow.setDescriptionWindowSize( |
||||
getPreferredDescWindowSize()); |
||||
} |
||||
return popupWindow; |
||||
} |
||||
} |
@ -0,0 +1,78 @@
|
||||
package com.fr.design.gui.ilable; |
||||
|
||||
import javax.swing.JLabel; |
||||
import java.awt.Dimension; |
||||
import java.awt.FontMetrics; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class UIAutoChangeLineLabel extends JLabel { |
||||
private final String text; |
||||
private final int width; |
||||
|
||||
|
||||
public UIAutoChangeLineLabel(String text, int width) { |
||||
super(text); |
||||
this.text = text; |
||||
this.width = width; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void doLayout() { |
||||
super.doLayout(); |
||||
this.setText(wrapperHtmlText()); |
||||
} |
||||
|
||||
private String wrapperHtmlText() { |
||||
List<String> stringList = autoChangeLine(this.getWidth()); |
||||
StringBuilder builder = new StringBuilder("<html>"); |
||||
for (String s : stringList) { |
||||
//用THML标签进行拼接,以实现自动换行
|
||||
builder.append(s).append("<br/>"); |
||||
} |
||||
builder.append("</html>"); |
||||
return builder.toString(); |
||||
} |
||||
|
||||
private List<String> autoChangeLine(int width) { |
||||
List<String> result = new ArrayList<>(); |
||||
if (width <= 0) { |
||||
result.add(this.text); |
||||
} else { |
||||
|
||||
char[] chars = this.text.toCharArray(); |
||||
//获取字体计算大小
|
||||
FontMetrics fontMetrics = this.getFontMetrics(this.getFont()); |
||||
int start = 0; |
||||
int len = 0; |
||||
while (start + len < this.text.length()) { |
||||
while (true) { |
||||
len++; |
||||
if (start + len > this.text.length()) |
||||
break; |
||||
if (fontMetrics.charsWidth(chars, start, len) |
||||
> width) { |
||||
break; |
||||
} |
||||
} |
||||
result.add(String.copyValueOf(chars, start, len - 1)); |
||||
start = start + len - 1; |
||||
len = 0; |
||||
} |
||||
if (this.text.length() - start > 0) { |
||||
result.add(String.copyValueOf(chars, start, this.text.length() - start)); |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public Dimension getPreferredSize() { |
||||
Dimension preferredSize = super.getPreferredSize(); |
||||
List<String> stringList = autoChangeLine(width); |
||||
FontMetrics fontMetrics = this.getFontMetrics(this.getFont()); |
||||
return new Dimension(preferredSize.width, fontMetrics.getHeight() * stringList.size()); |
||||
} |
||||
} |
@ -0,0 +1,858 @@
|
||||
package com.fr.design.javascript; |
||||
|
||||
import com.fr.design.border.UIRoundedBorder; |
||||
import com.fr.design.constants.UIConstants; |
||||
import com.fr.design.gui.autocomplete.AutoCompleteExtraRefreshComponent; |
||||
import com.fr.design.gui.autocomplete.BasicCompletion; |
||||
import com.fr.design.gui.autocomplete.CompletionCellRenderer; |
||||
import com.fr.design.gui.autocomplete.CompletionProvider; |
||||
import com.fr.design.gui.autocomplete.DefaultCompletionProvider; |
||||
import com.fr.design.gui.autocomplete.JSImplPaneAutoCompletion; |
||||
import com.fr.design.gui.ibutton.UIButton; |
||||
import com.fr.design.gui.icontainer.UIScrollPane; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.itextarea.UITextArea; |
||||
import com.fr.design.gui.itextfield.UITextField; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.javascript.jsapi.JSAPITreeHelper; |
||||
import com.fr.design.javascript.jsapi.JSAPIUserObject; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.general.CloudCenter; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.general.http.HttpToolbox; |
||||
import com.fr.json.JSONArray; |
||||
import com.fr.json.JSONException; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StringUtils; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Desktop; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.FocusAdapter; |
||||
import java.awt.event.FocusEvent; |
||||
import java.awt.event.KeyAdapter; |
||||
import java.awt.event.KeyEvent; |
||||
import java.awt.event.KeyListener; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
import java.awt.event.MouseListener; |
||||
import java.io.IOException; |
||||
import java.net.URI; |
||||
import java.net.URISyntaxException; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.Comparator; |
||||
import java.util.List; |
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.DefaultListCellRenderer; |
||||
import javax.swing.DefaultListModel; |
||||
import javax.swing.JComponent; |
||||
import javax.swing.JList; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPopupMenu; |
||||
import javax.swing.JScrollPane; |
||||
import javax.swing.JTree; |
||||
import javax.swing.event.ListSelectionEvent; |
||||
import javax.swing.event.ListSelectionListener; |
||||
import javax.swing.event.TreeSelectionEvent; |
||||
import javax.swing.event.TreeSelectionListener; |
||||
import javax.swing.tree.DefaultMutableTreeNode; |
||||
import javax.swing.tree.DefaultTreeCellRenderer; |
||||
import javax.swing.tree.DefaultTreeModel; |
||||
import javax.swing.tree.TreeNode; |
||||
import javax.swing.tree.TreePath; |
||||
|
||||
public class JSContentWithDescriptionPane extends JSContentPane implements KeyListener { |
||||
|
||||
//搜索关键词输入框
|
||||
private UITextField keyWordTextField = new UITextField(16); |
||||
//搜索出的提示列表
|
||||
private JList tipsList; |
||||
private DefaultListModel tipsListModel = new DefaultListModel(); |
||||
|
||||
private JList interfaceNameList; |
||||
private DefaultListModel interfaceNameModel; |
||||
|
||||
private JTree moduleTree; |
||||
|
||||
private DefaultCompletionProvider completionProvider; |
||||
private JSImplPaneAutoCompletion autoCompletion; |
||||
|
||||
//函数说明文本框
|
||||
private UITextArea descriptionTextArea; |
||||
|
||||
private JPopupMenu popupMenu; |
||||
|
||||
private InterfaceAndDescriptionPanel interfaceAndDescriptionPanel; |
||||
private JList helpDOCList; |
||||
|
||||
private int ifHasBeenWriten = 0; |
||||
private int currentPosition = 0; |
||||
private int beginPosition = 0; |
||||
private int insertPosition = 0; |
||||
private static final String SEPARATOR = "_"; |
||||
|
||||
private static final int KEY_10 = 10; |
||||
//上下左右
|
||||
private static final int KEY_37 = 37; |
||||
private static final int KEY_38 = 38; |
||||
private static final int KEY_39 = 39; |
||||
private static final int KEY_40 = 40; |
||||
|
||||
private static final String URL_FOR_TEST_NETWORK = "https://www.baidu.com"; |
||||
|
||||
private static final String DOCUMENT_SEARCH_URL = CloudCenter.getInstance().acquireUrlByKind("af.doc_search"); |
||||
|
||||
private String currentValue; |
||||
|
||||
public JSContentWithDescriptionPane(String[] args) { |
||||
this.setLayout(new BorderLayout()); |
||||
//===============================
|
||||
this.initFunctionTitle(args); |
||||
JPanel jsParaAndSearchPane = new JPanel(new BorderLayout()); |
||||
|
||||
//js函数声明面板
|
||||
JPanel jsParaPane = createJSParaPane(); |
||||
|
||||
jsParaPane.setPreferredSize(new Dimension(650, 80)); |
||||
//右上角的搜索提示面板
|
||||
JPanel tipsPane = createTipsPane(); |
||||
|
||||
jsParaAndSearchPane.add(jsParaPane, BorderLayout.CENTER); |
||||
jsParaAndSearchPane.add(tipsPane, BorderLayout.EAST); |
||||
|
||||
initPopTips(); |
||||
|
||||
//js文本编辑面板
|
||||
UIScrollPane contentTextAreaPanel = createContentTextAreaPanel(); |
||||
initContextAreaListener(); |
||||
|
||||
contentTextAreaPanel.setPreferredSize(new Dimension(850, 250)); |
||||
//js函数结束标签
|
||||
UILabel endBracketsLabel = new UILabel(); |
||||
endBracketsLabel.setText("}"); |
||||
|
||||
//结尾括号和复用函数按钮面板
|
||||
JPanel endBracketsPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
endBracketsPanel.add(endBracketsLabel, BorderLayout.WEST); |
||||
|
||||
JPanel northPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
northPanel.add(jsParaAndSearchPane, BorderLayout.NORTH); |
||||
|
||||
northPanel.add(contentTextAreaPanel, BorderLayout.CENTER); |
||||
northPanel.add(endBracketsPanel, BorderLayout.SOUTH); |
||||
|
||||
//主编辑框,也就是面板的正中间部分
|
||||
this.add(northPanel, BorderLayout.CENTER); |
||||
|
||||
//函数分类和函数说明面板==================================
|
||||
JPanel functionNameAndDescriptionPanel = createInterfaceAndDescriptionPanel(); |
||||
functionNameAndDescriptionPanel.setPreferredSize(new Dimension(880, 220)); |
||||
|
||||
this.add(functionNameAndDescriptionPanel, BorderLayout.SOUTH); |
||||
} |
||||
|
||||
private void initContextAreaListener() { |
||||
contentTextArea.addKeyListener(new KeyAdapter() { |
||||
@Override |
||||
public void keyTyped(KeyEvent e) { |
||||
if ((e.getKeyChar() >= 'A' && e.getKeyChar() <= 'z') || e.getKeyChar() == '_') { |
||||
if (autoCompletion != null) { |
||||
autoCompletion.doCompletion(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void keyReleased(KeyEvent e) { |
||||
contentTextArea.setForeground(Color.black); |
||||
} |
||||
}); |
||||
contentTextArea.addKeyListener(this); |
||||
contentTextArea.addFocusListener(new FocusAdapter() { |
||||
@Override |
||||
public void focusGained(FocusEvent e) { |
||||
if (autoCompletion == null) { |
||||
installAutoCompletion(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void focusLost(FocusEvent e) { |
||||
uninstallAutoCompletion(); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@Override |
||||
public void keyTyped(KeyEvent e) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void keyPressed(KeyEvent e) { |
||||
if (ifHasBeenWriten == 0) { |
||||
this.contentTextArea.setText(StringUtils.EMPTY); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void keyReleased(KeyEvent e) { |
||||
int key = e.getKeyCode(); |
||||
if (key == KEY_38 || key == KEY_40 || key == KEY_37 || key == KEY_39 || key == KEY_10) //如果是删除符号 ,为了可读性 没有和其他按键的程序相融合
|
||||
{ |
||||
currentPosition = contentTextArea.getCaretPosition(); |
||||
insertPosition = currentPosition; |
||||
beginPosition = getBeginPosition(); |
||||
} else { |
||||
if (contentTextArea.getText().trim().length() == 0) { |
||||
insertPosition = 0; |
||||
} else { |
||||
contentTextArea.setForeground(Color.black); |
||||
currentPosition = contentTextArea.getCaretPosition(); |
||||
beginPosition = getBeginPosition(); |
||||
insertPosition = beginPosition; |
||||
ifHasBeenWriten = 1; |
||||
} |
||||
} |
||||
} |
||||
|
||||
private int getBeginPosition() { |
||||
int i = currentPosition; |
||||
String textArea = contentTextArea.getText(); |
||||
for (; i > 0; i--) { |
||||
String tested = textArea.substring(i - 1, i).toUpperCase(); |
||||
char[] testedChar = tested.toCharArray(); |
||||
if (isChar(testedChar[0]) || isNum(testedChar[0])) { |
||||
continue; |
||||
} else { |
||||
break; |
||||
} |
||||
} |
||||
return i; |
||||
} |
||||
|
||||
private static boolean isNum(char tested) { |
||||
return tested >= '0' && tested <= '9'; |
||||
} |
||||
|
||||
private boolean isChar(char tested) { |
||||
return tested >= 'A' && tested <= 'Z' || tested >= 'a' && tested < 'z'; |
||||
} |
||||
|
||||
public class InterfaceAndDescriptionPanel extends JPanel implements AutoCompleteExtraRefreshComponent { |
||||
@Override |
||||
public void refresh(String replacementText) { |
||||
fixInterfaceNameList(replacementText); |
||||
} |
||||
} |
||||
|
||||
private void fixInterfaceNameList(String interfaceName) { |
||||
DefaultTreeModel defaultTreeModel = (DefaultTreeModel) moduleTree.getModel(); |
||||
TreeNode root = (TreeNode) defaultTreeModel.getRoot(); |
||||
String directCategory = JSAPITreeHelper.getDirectCategory(interfaceName); |
||||
if (directCategory == null) { |
||||
return; |
||||
} |
||||
setModuleTreeSelection(root, directCategory, defaultTreeModel); |
||||
interfaceNameModel = (DefaultListModel) interfaceNameList.getModel(); |
||||
interfaceNameModel.clear(); |
||||
List<String> interfaceNames = JSAPITreeHelper.getNames(directCategory); |
||||
int index = 0; |
||||
for (int i = 0; i < interfaceNames.size(); i++) { |
||||
interfaceNameModel.addElement(interfaceNames.get(i)); |
||||
if (StringUtils.equals(interfaceNames.get(i), interfaceName)) { |
||||
index = i; |
||||
} |
||||
} |
||||
interfaceNameList.setSelectedIndex(index); |
||||
interfaceNameList.ensureIndexIsVisible(index); |
||||
} |
||||
|
||||
private boolean setModuleTreeSelection(TreeNode node, String directCategory, DefaultTreeModel treeModel) { |
||||
|
||||
DefaultMutableTreeNode defaultMutableTreeNode = (DefaultMutableTreeNode) node; |
||||
Object userObject = defaultMutableTreeNode.getUserObject(); |
||||
if (userObject instanceof JSAPIUserObject) { |
||||
String value = ((JSAPIUserObject) userObject).getValue(); |
||||
if (StringUtils.equals(value, directCategory)) { |
||||
moduleTree.setSelectionPath(new TreePath(treeModel.getPathToRoot(node))); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
for (int i = 0; i < node.getChildCount(); i++) { |
||||
if (setModuleTreeSelection(node.getChildAt(i), directCategory, treeModel)) { |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
private JPanel createInterfaceAndDescriptionPanel() { |
||||
interfaceAndDescriptionPanel = new InterfaceAndDescriptionPanel(); |
||||
interfaceAndDescriptionPanel.setLayout(new BorderLayout(4, 4)); |
||||
JPanel interfacePanel = new JPanel(new BorderLayout(4, 4)); |
||||
interfaceAndDescriptionPanel.add(interfacePanel, BorderLayout.WEST); |
||||
JPanel descriptionAndDocumentPanel = new JPanel(new BorderLayout(4, 4)); |
||||
//函数说明和帮助文档框
|
||||
initDescriptionArea(descriptionAndDocumentPanel); |
||||
|
||||
//模块和接口面板
|
||||
initInterfaceModuleTree(interfacePanel); |
||||
initInterfaceNameList(interfacePanel); |
||||
|
||||
initHelpDocumentPane(descriptionAndDocumentPanel); |
||||
|
||||
interfaceAndDescriptionPanel.add(descriptionAndDocumentPanel, BorderLayout.CENTER); |
||||
return interfaceAndDescriptionPanel; |
||||
} |
||||
|
||||
private void doHelpDocumentSearch() { |
||||
Object value = interfaceNameList.getSelectedValue(); |
||||
if (value != null) { |
||||
String url = DOCUMENT_SEARCH_URL + value.toString(); |
||||
try { |
||||
String result = HttpToolbox.get(url); |
||||
JSONObject jsonObject = new JSONObject(result); |
||||
JSONArray jsonArray = jsonObject.optJSONArray("list"); |
||||
if (jsonArray != null) { |
||||
DefaultListModel helpDOCModel = (DefaultListModel) helpDOCList.getModel(); |
||||
helpDOCModel.clear(); |
||||
for (int i = 0; i < jsonArray.length(); i++) { |
||||
JSONObject resultJSONObject = jsonArray.optJSONObject(i); |
||||
String docURL = resultJSONObject.optString("url"); |
||||
String name = resultJSONObject.optString("title").trim(); |
||||
HelpDocument helpDocument = new HelpDocument(docURL, name); |
||||
helpDOCModel.addElement(helpDocument); |
||||
} |
||||
} |
||||
} catch (JSONException e) { |
||||
FineLoggerFactory.getLogger().debug(e.getMessage(), e); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void initHelpDocumentPane(JPanel descriptionAndDocumentPanel) { |
||||
UIScrollPane helpDOCScrollPane; |
||||
if (isNetworkOk()) { |
||||
helpDOCList = new JList(new DefaultListModel()); |
||||
initHelpDOCListRender(); |
||||
initHelpDOCListListener(); |
||||
helpDOCScrollPane = new UIScrollPane(helpDOCList); |
||||
doHelpDocumentSearch(); |
||||
} else { |
||||
UILabel label1 = new UILabel(Toolkit.i18nText("Fine-Design_Net_Connect_Failed"), 0); |
||||
label1.setPreferredSize(new Dimension(180, 20)); |
||||
UILabel label2 = new UILabel(Toolkit.i18nText("Fine-Design_Basic_Reload"), 0); |
||||
label2.setPreferredSize(new Dimension(180, 20)); |
||||
label2.setForeground(Color.blue); |
||||
JPanel labelPane = FRGUIPaneFactory.createVerticalFlowLayout_Pane(true, 0, 0, 0); |
||||
labelPane.setBackground(Color.WHITE); |
||||
labelPane.add(label1); |
||||
labelPane.add(label2); |
||||
JPanel containerPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
containerPanel.add(labelPane, BorderLayout.CENTER); |
||||
helpDOCScrollPane = new UIScrollPane(containerPanel); |
||||
label2.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
descriptionAndDocumentPanel.removeAll(); |
||||
initHelpDocumentPane(descriptionAndDocumentPanel); |
||||
|
||||
} |
||||
}); |
||||
} |
||||
helpDOCScrollPane.setPreferredSize(new Dimension(200, 200)); |
||||
helpDOCScrollPane.setBorder(null); |
||||
descriptionAndDocumentPanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Relevant_Cases"), helpDOCScrollPane), BorderLayout.EAST); |
||||
|
||||
} |
||||
|
||||
private void initHelpDOCListListener() { |
||||
helpDOCList.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseClicked(MouseEvent e) { |
||||
if (e.getClickCount() == 2) { |
||||
Object value = helpDOCList.getSelectedValue(); |
||||
if (value instanceof HelpDocument) { |
||||
String url = ((HelpDocument) value).getDocumentUrl(); |
||||
try { |
||||
Desktop.getDesktop().browse(new URI(url)); |
||||
} catch (IOException ex) { |
||||
FineLoggerFactory.getLogger().error(ex.getMessage(), ex); |
||||
} catch (URISyntaxException ex) { |
||||
FineLoggerFactory.getLogger().error(ex.getMessage(), ex); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void initHelpDOCListRender() { |
||||
helpDOCList.setCellRenderer(new DefaultListCellRenderer() { |
||||
@Override |
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { |
||||
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); |
||||
if (value instanceof HelpDocument) { |
||||
this.setText(((HelpDocument) value).getName()); |
||||
this.setForeground(Color.BLUE); |
||||
} |
||||
return this; |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private static boolean isNetworkOk() { |
||||
try { |
||||
HttpToolbox.get(URL_FOR_TEST_NETWORK); |
||||
return true; |
||||
} catch (Exception ignore) { |
||||
// 网络异常
|
||||
return false; |
||||
} |
||||
} |
||||
|
||||
private static class HelpDocument { |
||||
private String documentUrl; |
||||
|
||||
|
||||
private String name; |
||||
|
||||
public HelpDocument(String documentUrl, String name) { |
||||
this.documentUrl = documentUrl; |
||||
this.name = name; |
||||
} |
||||
|
||||
public String getDocumentUrl() { |
||||
return documentUrl; |
||||
} |
||||
|
||||
public String getName() { |
||||
return name; |
||||
} |
||||
} |
||||
|
||||
private void initDescriptionArea(JPanel descriptionPanel) { |
||||
descriptionTextArea = new UITextArea(); |
||||
UIScrollPane descriptionScrollPane = new UIScrollPane(descriptionTextArea); |
||||
descriptionScrollPane.setPreferredSize(new Dimension(300, 200)); |
||||
descriptionPanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Interface_Description"), descriptionScrollPane), BorderLayout.CENTER); |
||||
descriptionTextArea.setBackground(Color.white); |
||||
descriptionTextArea.setLineWrap(true); |
||||
descriptionTextArea.setWrapStyleWord(true); |
||||
descriptionTextArea.setEditable(false); |
||||
} |
||||
|
||||
private void installAutoCompletion() { |
||||
CompletionProvider provider = createCompletionProvider(); |
||||
autoCompletion = new JSImplPaneAutoCompletion(provider); |
||||
autoCompletion.setListCellRenderer(new CompletionCellRenderer()); |
||||
autoCompletion.install(contentTextArea); |
||||
autoCompletion.installExtraRefreshComponent(interfaceAndDescriptionPanel); |
||||
} |
||||
|
||||
private void uninstallAutoCompletion() { |
||||
if (autoCompletion != null) { |
||||
autoCompletion.uninstall(); |
||||
autoCompletion = null; |
||||
} |
||||
} |
||||
|
||||
private CompletionProvider createCompletionProvider() { |
||||
if (completionProvider == null) { |
||||
completionProvider = new DefaultCompletionProvider(); |
||||
for (String name : JSAPITreeHelper.getAllNames()) { |
||||
completionProvider.addCompletion(new BasicCompletion(completionProvider, name)); |
||||
} |
||||
} |
||||
return completionProvider; |
||||
} |
||||
|
||||
private void initInterfaceModuleTree(JPanel interfacePanel) { |
||||
moduleTree = new JTree(); |
||||
UIScrollPane moduleTreePane = new UIScrollPane(moduleTree); |
||||
moduleTreePane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); |
||||
interfacePanel.add(this.createNamePane(Toolkit.i18nText("Fine-Design_Module"), moduleTreePane), BorderLayout.WEST); |
||||
moduleTreePane.setPreferredSize(new Dimension(180, 200)); |
||||
|
||||
moduleTree.setRootVisible(false); |
||||
moduleTree.setShowsRootHandles(true); |
||||
moduleTree.setCellRenderer(moduleTreeCellRender); |
||||
DefaultTreeModel moduleTreeModel = (DefaultTreeModel) moduleTree.getModel(); |
||||
DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) moduleTreeModel.getRoot(); |
||||
rootNode.removeAllChildren(); |
||||
|
||||
JSAPITreeHelper.createJSAPITree(rootNode); |
||||
moduleTreeModel.reload(); |
||||
|
||||
initModuleTreeSelectionListener(); |
||||
} |
||||
|
||||
private void initModuleTreeSelectionListener() { |
||||
moduleTree.addTreeSelectionListener(new TreeSelectionListener() { |
||||
@Override |
||||
public void valueChanged(TreeSelectionEvent e) { |
||||
DefaultMutableTreeNode selectedTreeNode = (DefaultMutableTreeNode) moduleTree.getLastSelectedPathComponent(); |
||||
Object selectedValue = selectedTreeNode.getUserObject(); |
||||
if (null == selectedValue) { |
||||
return; |
||||
} |
||||
if (selectedValue instanceof JSAPIUserObject) { |
||||
interfaceNameModel = (DefaultListModel) interfaceNameList.getModel(); |
||||
interfaceNameModel.clear(); |
||||
String text = ((JSAPIUserObject) selectedValue).getValue(); |
||||
List<String> allInterfaceNames = JSAPITreeHelper.getNames(text); |
||||
for (String interfaceName : allInterfaceNames) { |
||||
interfaceNameModel.addElement(interfaceName); |
||||
} |
||||
if (interfaceNameModel.size() > 0) { |
||||
interfaceNameList.setSelectedIndex(0); |
||||
setDescription(interfaceNameList.getSelectedValue().toString()); |
||||
interfaceNameList.ensureIndexIsVisible(0); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
private DefaultTreeCellRenderer moduleTreeCellRender = new DefaultTreeCellRenderer() { |
||||
public Component getTreeCellRendererComponent(JTree tree, |
||||
Object value, boolean selected, boolean expanded, |
||||
boolean leaf, int row, boolean hasFocus) { |
||||
super.getTreeCellRendererComponent(tree, value, selected, |
||||
expanded, leaf, row, hasFocus); |
||||
|
||||
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) value; |
||||
Object userObj = treeNode.getUserObject(); |
||||
if (userObj instanceof JSAPIUserObject) { |
||||
this.setText(((JSAPIUserObject) userObj).getDisplayText()); |
||||
this.setIcon(null); |
||||
} |
||||
return this; |
||||
} |
||||
|
||||
}; |
||||
|
||||
|
||||
private void initInterfaceNameList(JPanel interfacePanel) { |
||||
interfaceNameList = new JList(new DefaultListModel()); |
||||
UIScrollPane interfaceNamePanelScrollPane = new UIScrollPane(interfaceNameList); |
||||
interfaceNamePanelScrollPane.setPreferredSize(new Dimension(180, 200)); |
||||
interfacePanel.add( |
||||
this.createNamePane(Toolkit.i18nText("Fine-Design_Interface") + ":", interfaceNamePanelScrollPane), |
||||
BorderLayout.CENTER); |
||||
|
||||
interfaceNamePanelScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); |
||||
initInterfaceNameModule(); |
||||
initInterfaceNameListSelectionListener(); |
||||
initInterfaceNameListMouseListener(); |
||||
} |
||||
|
||||
private void initInterfaceNameModule() { |
||||
moduleTree.setSelectionPath(moduleTree.getPathForRow(0)); |
||||
} |
||||
|
||||
private void setDescription(String interfaceName) { |
||||
StringBuilder il8Key = new StringBuilder(); |
||||
moduleTree.getSelectionPath().getPath(); |
||||
Object obj = moduleTree.getSelectionPath().getPath()[moduleTree.getSelectionPath().getPath().length - 1]; |
||||
Object userObject = ((DefaultMutableTreeNode) obj).getUserObject(); |
||||
if (userObject instanceof JSAPIUserObject) { |
||||
il8Key.append(JSAPITreeHelper.getDirectCategory(interfaceName)); |
||||
} |
||||
interfaceName = interfaceName.toUpperCase(); |
||||
if (!interfaceName.startsWith(SEPARATOR)) { |
||||
interfaceName = SEPARATOR + interfaceName; |
||||
} |
||||
il8Key.append(interfaceName); |
||||
descriptionTextArea.setText(Toolkit.i18nText(il8Key.toString())); |
||||
descriptionTextArea.moveCaretPosition(0); |
||||
} |
||||
|
||||
private void initInterfaceNameListSelectionListener() { |
||||
interfaceNameList.addListSelectionListener(new ListSelectionListener() { |
||||
|
||||
public void valueChanged(ListSelectionEvent evt) { |
||||
Object selectedValue = interfaceNameList.getSelectedValue(); |
||||
if (selectedValue == null) { |
||||
return; |
||||
} |
||||
String interfaceName = selectedValue.toString(); |
||||
if (!StringUtils.equals(interfaceName, currentValue)) { |
||||
setDescription(interfaceName); |
||||
doHelpDocumentSearch(); |
||||
currentValue = interfaceName; |
||||
} |
||||
|
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
private void initInterfaceNameListMouseListener() { |
||||
interfaceNameList.addMouseListener(new MouseAdapter() { |
||||
public void mouseClicked(MouseEvent evt) { |
||||
if (evt.getClickCount() >= 2) { |
||||
Object selectedValue = interfaceNameList.getSelectedValue(); |
||||
String interfaceName = selectedValue.toString(); |
||||
applyText(interfaceName); |
||||
} |
||||
} |
||||
}); |
||||
} |
||||
|
||||
private void applyText(String text) { |
||||
if (text == null || text.length() <= 0) { |
||||
return; |
||||
} |
||||
if (ifHasBeenWriten == 0) { |
||||
contentTextArea.setForeground(Color.black); |
||||
contentTextArea.setText(StringUtils.EMPTY); |
||||
ifHasBeenWriten = 1; |
||||
insertPosition = 0; |
||||
} |
||||
String textAll = contentTextArea.getText(); |
||||
currentPosition = contentTextArea.getCaretPosition(); |
||||
int insert = 0; |
||||
int current = 0; |
||||
if (insertPosition <= currentPosition) { |
||||
insert = insertPosition; |
||||
current = currentPosition; |
||||
} else { |
||||
insert = currentPosition; |
||||
current = insertPosition; |
||||
} |
||||
String beforeIndexOfInsertString = textAll.substring(0, insert); |
||||
String afterIndexofInsertString = textAll.substring(current); |
||||
contentTextArea.setText(beforeIndexOfInsertString + text + afterIndexofInsertString); |
||||
contentTextArea.getText(); |
||||
contentTextArea.requestFocus(); |
||||
insertPosition = contentTextArea.getCaretPosition(); |
||||
} |
||||
|
||||
private JPanel createNamePane(String name, JComponent comp) { |
||||
JPanel namePane = new JPanel(new BorderLayout(4, 4)); |
||||
namePane.add(new UILabel(name), BorderLayout.NORTH); |
||||
namePane.add(comp, BorderLayout.CENTER); |
||||
return namePane; |
||||
} |
||||
|
||||
private JPanel createTipsPane() { |
||||
JPanel tipsPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
tipsPane.setLayout(new BorderLayout(4, 4)); |
||||
tipsPane.setBorder(BorderFactory.createEmptyBorder(30, 2, 0, 0)); |
||||
JPanel searchPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
searchPane.setLayout(new BorderLayout(4, 4)); |
||||
searchPane.add(keyWordTextField, BorderLayout.CENTER); |
||||
|
||||
//搜索按钮
|
||||
UIButton searchButton = new UIButton(Toolkit.i18nText("Fine-Design_Basic_Search")); |
||||
searchButton.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
String toFind = keyWordTextField.getText(); |
||||
search(toFind); |
||||
popTips(); |
||||
tipsList.requestFocusInWindow(); |
||||
} |
||||
}); |
||||
|
||||
keyWordTextField.addKeyListener(new KeyAdapter() { |
||||
@Override |
||||
public void keyPressed(KeyEvent e) { |
||||
if (e.getKeyChar() == KeyEvent.VK_ENTER) { |
||||
e.consume(); |
||||
String toFind = keyWordTextField.getText(); |
||||
search(toFind); |
||||
popTips(); |
||||
tipsList.requestFocusInWindow(); |
||||
} |
||||
} |
||||
}); |
||||
|
||||
searchPane.add(searchButton, BorderLayout.EAST); |
||||
tipsPane.add(searchPane, BorderLayout.NORTH); |
||||
|
||||
tipsList = new JList(tipsListModel); |
||||
tipsList.addMouseListener(tipsListMouseListener); |
||||
tipsList.addListSelectionListener(tipsListSelectionListener); |
||||
tipsList.addKeyListener(tipListKeyListener); |
||||
|
||||
return tipsPane; |
||||
} |
||||
|
||||
private void search(String key) { |
||||
tipsListModel.removeAllElements(); |
||||
tipsListModel.clear(); |
||||
key = key.replaceAll(StringUtils.BLANK, StringUtils.EMPTY); |
||||
ArrayList<String> list = new ArrayList<>(); |
||||
if (!StringUtils.isEmpty(key)) { |
||||
List<String> allNames = JSAPITreeHelper.getAllNames(); |
||||
for (String name : allNames) { |
||||
if (searchResult(key, name)) { |
||||
list.add(name); |
||||
} |
||||
} |
||||
String finalKey = key; |
||||
Collections.sort(list, new Comparator<String>() { |
||||
@Override |
||||
public int compare(String o1, String o2) { |
||||
int result; |
||||
boolean o1StartWidth = o1.toLowerCase().startsWith(finalKey.toLowerCase()); |
||||
boolean o2StartWidth = o2.toLowerCase().startsWith(finalKey.toLowerCase()); |
||||
if (o1StartWidth) { |
||||
result = o2StartWidth ? o1.compareTo(o2) : -1; |
||||
} else { |
||||
result = o2StartWidth ? 1 : o1.compareTo(o2); |
||||
} |
||||
return result; |
||||
} |
||||
}); |
||||
for (String name : list) { |
||||
tipsListModel.addElement(name); |
||||
} |
||||
if (!tipsListModel.isEmpty()) { |
||||
tipsList.setSelectedIndex(0); |
||||
} |
||||
} |
||||
} |
||||
|
||||
private boolean searchResult(String key, String interfaceName) { |
||||
if (StringUtils.isBlank(key) || StringUtils.isBlank(interfaceName)) { |
||||
return false; |
||||
} |
||||
int length = key.length(); |
||||
String temp = interfaceName.toUpperCase(); |
||||
for (int i = 0; i < length; i++) { |
||||
String check = key.substring(i, i + 1); |
||||
int index = temp.indexOf(check.toUpperCase()); |
||||
if (index == -1) { |
||||
return false; |
||||
} else { |
||||
temp = temp.substring(index + 1); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
private void initPopTips() { |
||||
popupMenu = new JPopupMenu(); |
||||
JScrollPane tipsScrollPane = new JScrollPane(tipsList); |
||||
popupMenu.add(tipsScrollPane); |
||||
tipsScrollPane.setPreferredSize(new Dimension(220, 146)); |
||||
tipsScrollPane.setBorder(new UIRoundedBorder(UIConstants.LINE_COLOR, 1, UIConstants.ARC)); |
||||
} |
||||
|
||||
private void popTips() { |
||||
popupMenu.show(keyWordTextField, 0, 23); |
||||
} |
||||
|
||||
private ListSelectionListener tipsListSelectionListener = new ListSelectionListener() { |
||||
@Override |
||||
public void valueChanged(ListSelectionEvent e) { |
||||
Object selectValue = tipsList.getSelectedValue(); |
||||
if (selectValue == null) { |
||||
return; |
||||
} |
||||
String interfaceName = selectValue.toString(); |
||||
fixInterfaceNameList(interfaceName); |
||||
} |
||||
}; |
||||
|
||||
private KeyListener tipListKeyListener = new KeyAdapter() { |
||||
@Override |
||||
public void keyPressed(KeyEvent e) { |
||||
if (e.getKeyChar() == KeyEvent.VK_ENTER) { |
||||
Object selectValue = tipsList.getSelectedValue(); |
||||
if (selectValue == null) { |
||||
return; |
||||
} |
||||
tipListValueSelectAction(selectValue.toString()); |
||||
if (popupMenu != null) { |
||||
popupMenu.setVisible(false); |
||||
} |
||||
contentTextArea.requestFocusInWindow(); |
||||
} |
||||
} |
||||
}; |
||||
|
||||
private void tipListValueSelectAction(String value) { |
||||
if (ifHasBeenWriten == 0) { |
||||
contentTextArea.setForeground(Color.black); |
||||
contentTextArea.setText(StringUtils.EMPTY); |
||||
} |
||||
contentTextArea.setForeground(Color.black); |
||||
currentPosition = contentTextArea.getCaretPosition(); |
||||
String output = value; |
||||
String textAll = contentTextArea.getText(); |
||||
String textReplaced; |
||||
int position = 0; |
||||
if (insertPosition <= currentPosition) { |
||||
textReplaced = textAll.substring(0, insertPosition) + output + textAll.substring(currentPosition); |
||||
position = insertPosition + output.length(); |
||||
} else { |
||||
textReplaced = textAll.substring(0, currentPosition) + output + textAll.substring(insertPosition); |
||||
position = currentPosition + output.length(); |
||||
} |
||||
contentTextArea.setText(textReplaced); |
||||
contentTextArea.setCaretPosition(position); |
||||
insertPosition = position; |
||||
ifHasBeenWriten = 1; |
||||
tipsListModel.removeAllElements(); |
||||
} |
||||
|
||||
private MouseListener tipsListMouseListener = new MouseAdapter() { |
||||
String singlePressContent; |
||||
|
||||
String doublePressContent; |
||||
|
||||
@Override |
||||
public void mousePressed(MouseEvent e) { |
||||
int index = tipsList.getSelectedIndex(); |
||||
if (index != -1) { |
||||
if (e.getClickCount() == 1) { |
||||
singlePressContent = (String) tipsListModel.getElementAt(index); |
||||
} else if (e.getClickCount() == 2) { |
||||
doublePressContent = (String) tipsListModel.getElementAt(index); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void mouseReleased(MouseEvent e) { |
||||
int index = tipsList.getSelectedIndex(); |
||||
if (index != -1) { |
||||
if (e.getClickCount() == 1) { |
||||
if (ComparatorUtils.equals((String) tipsListModel.getElementAt(index), singlePressContent)) { |
||||
singleClickActuator(singlePressContent); |
||||
} |
||||
} else if (e.getClickCount() == 2) { |
||||
if (ComparatorUtils.equals((String) tipsListModel.getElementAt(index), doublePressContent)) { |
||||
doubleClickActuator(doublePressContent); |
||||
} |
||||
if (popupMenu != null) { |
||||
popupMenu.setVisible(false); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private void singleClickActuator(String currentLineContent) { |
||||
setDescription(currentLineContent); |
||||
fixInterfaceNameList(currentLineContent); |
||||
} |
||||
|
||||
private void doubleClickActuator(String currentLineContent) { |
||||
tipListValueSelectAction(currentLineContent); |
||||
} |
||||
}; |
||||
} |
@ -0,0 +1,23 @@
|
||||
package com.fr.design.javascript; |
||||
|
||||
|
||||
import com.fr.js.JavaScriptImpl; |
||||
|
||||
|
||||
public class NewJavaScriptImplPane extends JavaScriptImplPane { |
||||
public NewJavaScriptImplPane(String[] args) { |
||||
super(args); |
||||
} |
||||
|
||||
protected JSContentPane createJSContentPane(String[] defaultArgs){ |
||||
return new JSContentWithDescriptionPane(defaultArgs); |
||||
} |
||||
|
||||
public void populate(JavaScriptImpl javaScript) { |
||||
if (javaScript != null) { |
||||
populateBean(javaScript); |
||||
} else { |
||||
jsPane.reset(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,21 @@
|
||||
package com.fr.design.javascript.jsapi; |
||||
|
||||
import com.fr.design.i18n.Toolkit; |
||||
|
||||
public class CategoryTreeNodesUserObject implements JSAPIUserObject { |
||||
private String value; |
||||
|
||||
public CategoryTreeNodesUserObject(String value) { |
||||
this.value = value; |
||||
} |
||||
|
||||
@Override |
||||
public String getValue() { |
||||
return value; |
||||
} |
||||
|
||||
@Override |
||||
public String getDisplayText() { |
||||
return Toolkit.i18nText(value); |
||||
} |
||||
} |
@ -0,0 +1,155 @@
|
||||
package com.fr.design.javascript.jsapi; |
||||
|
||||
import com.fr.general.IOUtils; |
||||
import com.fr.json.JSONArray; |
||||
import com.fr.json.JSONObject; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.stable.StringUtils; |
||||
import java.io.BufferedReader; |
||||
import java.io.InputStreamReader; |
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import javax.swing.tree.DefaultMutableTreeNode; |
||||
|
||||
public class JSAPITreeHelper { |
||||
private static final String JSAPI_PATH = "com/fr/design/javascript/jsapi/jsapi.json"; |
||||
private static final String CATEGORY_PATH = "com/fr/design/javascript/jsapi/category.json"; |
||||
private static JSONObject categoryJSON ; |
||||
private static JSONObject jsapiJSON ; |
||||
|
||||
static { |
||||
jsapiJSON = createJSON(JSAPI_PATH); |
||||
categoryJSON = createJSON(CATEGORY_PATH); |
||||
} |
||||
|
||||
private static JSONObject createJSON(String path) { |
||||
StringBuilder jsonString = new StringBuilder(StringUtils.EMPTY); |
||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(IOUtils.readResource(path)))) { |
||||
String s; |
||||
while ((s = bufferedReader.readLine()) != null) { |
||||
jsonString.append(s); |
||||
} |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
} |
||||
return new JSONObject(jsonString.toString()); |
||||
} |
||||
|
||||
|
||||
public static void createJSAPITree(DefaultMutableTreeNode rootNode) { |
||||
createJSAPITree(categoryJSON, rootNode); |
||||
} |
||||
|
||||
public static String getDirectCategory(String name) { |
||||
if (jsapiJSON != null) { |
||||
Iterator<String> it = jsapiJSON.keys(); |
||||
while (it.hasNext()) { |
||||
String key = it.next(); |
||||
JSONArray nameArray = jsapiJSON.optJSONArray(key); |
||||
for (int i = 0; i < nameArray.length(); i++) { |
||||
if (StringUtils.equals(nameArray.getString(i), name)) { |
||||
return key; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private static void createJSAPITree(JSONObject jsonObject, DefaultMutableTreeNode rootNode) { |
||||
if (jsonObject != null && rootNode != null) { |
||||
Iterator<String> it = jsonObject.keys(); |
||||
while (it.hasNext()) { |
||||
String key = it.next(); |
||||
JSONObject subNode = jsonObject.optJSONObject(key); |
||||
if (subNode.size() == 0) { |
||||
rootNode.add(new DefaultMutableTreeNode(new CategoryTreeNodesUserObject(key))); |
||||
} else { |
||||
DefaultMutableTreeNode treeNode = new DefaultMutableTreeNode(new CategoryTreeNodesUserObject(key)); |
||||
rootNode.add(treeNode); |
||||
createJSAPITree(subNode, treeNode); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
private static List<String> getAllSubNodes(String name) { |
||||
return getAllSubNodes(name, categoryJSON); |
||||
} |
||||
|
||||
public static List<String> getAllNames() { |
||||
ArrayList<String> result = new ArrayList<>(); |
||||
if (jsapiJSON != null) { |
||||
Iterator<String> it = jsapiJSON.keys(); |
||||
while (it.hasNext()) { |
||||
String key = it.next(); |
||||
JSONArray nameArray = jsapiJSON.optJSONArray(key); |
||||
for (int i = 0; i < nameArray.length(); i++) { |
||||
result.add(nameArray.getString(i)); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
public static List<String> getNames(String category) { |
||||
ArrayList<String> result = new ArrayList<>(); |
||||
List<String> subCategories = getAllSubNodes(category); |
||||
if (jsapiJSON != null) { |
||||
for (String subCategory : subCategories) { |
||||
if (jsapiJSON.containsKey(subCategory)) { |
||||
JSONArray nameArray = jsapiJSON.optJSONArray(subCategory); |
||||
for (int i = 0; i < nameArray.length(); i++) { |
||||
result.add(nameArray.getString(i)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private static List<String> getAllSubNodes(String name, JSONObject jsonObject) { |
||||
ArrayList<String> result = new ArrayList<>(); |
||||
if (jsonObject != null) { |
||||
Iterator<String> it = jsonObject.keys(); |
||||
while (it.hasNext()) { |
||||
String key = it.next(); |
||||
JSONObject subNode = jsonObject.optJSONObject(key); |
||||
if (subNode.size() == 0) { |
||||
if (StringUtils.equals(key, name)) { |
||||
result.add(key); |
||||
return result; |
||||
} |
||||
} else { |
||||
if (StringUtils.equals(key, name)) { |
||||
result.add(key); |
||||
result.addAll(getAllSubNodes(subNode)); |
||||
return result; |
||||
} else { |
||||
result.addAll(getAllSubNodes(name, subNode)); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
private static List<String> getAllSubNodes(JSONObject jsonObject) { |
||||
ArrayList<String> result = new ArrayList<>(); |
||||
if (jsonObject != null) { |
||||
Iterator<String> it = jsonObject.keys(); |
||||
while (it.hasNext()) { |
||||
String key = it.next(); |
||||
JSONObject subNode = jsonObject.optJSONObject(key); |
||||
if (subNode.size() == 0) { |
||||
result.add(key); |
||||
} else { |
||||
result.add(key); |
||||
result.addAll(getAllSubNodes(subNode)); |
||||
} |
||||
} |
||||
} |
||||
return result; |
||||
} |
||||
} |
@ -0,0 +1,9 @@
|
||||
package com.fr.design.javascript.jsapi; |
||||
|
||||
|
||||
public interface JSAPIUserObject { |
||||
|
||||
String getValue(); |
||||
|
||||
String getDisplayText(); |
||||
} |
@ -0,0 +1,7 @@
|
||||
package com.fr.design.javascript.jsapi; |
||||
|
||||
import com.fr.js.JavaScriptImpl; |
||||
|
||||
public interface JSImplPopulateAction { |
||||
void populate(JavaScriptImpl javaScript); |
||||
} |
@ -0,0 +1,7 @@
|
||||
package com.fr.design.javascript.jsapi; |
||||
|
||||
import com.fr.js.JavaScriptImpl; |
||||
|
||||
public interface JSImplUpdateAction { |
||||
void update(JavaScriptImpl javaScript); |
||||
} |
@ -0,0 +1,128 @@
|
||||
package com.fr.design.report.fit; |
||||
|
||||
|
||||
import com.fr.design.designer.properties.items.Item; |
||||
import com.fr.form.fit.common.LightTool; |
||||
import com.fr.form.main.BodyScaleAttrTransformer; |
||||
import com.fr.form.main.Form; |
||||
import com.fr.form.ui.container.WAbsoluteLayout; |
||||
import com.fr.form.ui.container.WBodyLayoutType; |
||||
import com.fr.form.ui.container.WFitLayout; |
||||
|
||||
public enum FormFitAttrModelType { |
||||
PLAIN_FORM_FIT_ATTR_MODEL { |
||||
@Override |
||||
public FitAttrModel getFitAttrModel() { |
||||
return new FrmFitAttrModel(); |
||||
} |
||||
|
||||
@Override |
||||
public Item[] getFitLayoutScaleAttr() { |
||||
return new Item[]{ |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WFitLayout.STATE_FULL), |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Horizontal_Adaptive"), WFitLayout.STATE_ORIGIN)}; |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public Item[] getAbsoluteLayoutSaleAttr() { |
||||
return new Item[]{ |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Scaling_Mode_Fit"), WAbsoluteLayout.STATE_FIT), |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Scaling_Mode_Fixed"), WAbsoluteLayout.STATE_FIXED) |
||||
}; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getScaleAttrShowIndex(WFitLayout wFitLayout) { |
||||
int scale = wFitLayout.getScaleAttr(); |
||||
if (wFitLayout.getBodyLayoutType() == WBodyLayoutType.FIT) { |
||||
return BodyScaleAttrTransformer.getFitBodyCompStateFromScaleAttr(scale); |
||||
} else { |
||||
return BodyScaleAttrTransformer.getAbsoluteBodyCompStateFromScaleAttr(scale); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int parseScaleAttrFromShowIndex(int showIndex, WBodyLayoutType wBodyLayoutType) { |
||||
if (wBodyLayoutType == WBodyLayoutType.FIT) { |
||||
if (showIndex == 0) { |
||||
return WFitLayout.SCALE_FULL; |
||||
} else { |
||||
return WFitLayout.SCALE_HOR; |
||||
} |
||||
} else { |
||||
if (showIndex == 0) { |
||||
return WFitLayout.SCALE_FULL; |
||||
} else { |
||||
return WFitLayout.SCALE_NO; |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
}, |
||||
NEW_FORM_FIT_ATTR_MODEL { |
||||
@Override |
||||
public FitAttrModel getFitAttrModel() { |
||||
return new AdaptiveFrmFitAttrModel(); |
||||
} |
||||
|
||||
@Override |
||||
public Item[] getFitLayoutScaleAttr() { |
||||
return new Item[]{ |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WFitLayout.STATE_FULL), |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Horizontal_Adaptive"), WFitLayout.STATE_ORIGIN), |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Scaling_Mode_Fixed"), 2)}; |
||||
} |
||||
|
||||
@Override |
||||
public Item[] getAbsoluteLayoutSaleAttr() { |
||||
return new Item[]{ |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Bidirectional_Adaptive"), WFitLayout.STATE_FULL), |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Horizontal_Adaptive"), WFitLayout.STATE_ORIGIN), |
||||
new Item(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Widget_Scaling_Mode_Fixed"), 2)}; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public int getScaleAttrShowIndex(WFitLayout wFitLayout) { |
||||
int scale = wFitLayout.getScaleAttr(); |
||||
if (scale == WFitLayout.SCALE_NO) { |
||||
return 2; |
||||
} else if (scale == WFitLayout.SCALE_HOR) { |
||||
return 1; |
||||
} else { |
||||
return 0; |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public int parseScaleAttrFromShowIndex(int showIndex, WBodyLayoutType wBodyLayoutType) { |
||||
if (showIndex == 0) { |
||||
return WFitLayout.SCALE_FULL; |
||||
} else if (showIndex == 1) { |
||||
return WFitLayout.SCALE_HOR; |
||||
} else { |
||||
return WFitLayout.SCALE_NO; |
||||
} |
||||
} |
||||
|
||||
|
||||
}; |
||||
|
||||
public abstract FitAttrModel getFitAttrModel(); |
||||
|
||||
public abstract Item[] getFitLayoutScaleAttr(); |
||||
|
||||
public abstract Item[] getAbsoluteLayoutSaleAttr(); |
||||
|
||||
public abstract int getScaleAttrShowIndex(WFitLayout wFitLayout); |
||||
|
||||
public abstract int parseScaleAttrFromShowIndex(int showIndex, WBodyLayoutType wBodyLayoutType); |
||||
|
||||
|
||||
public static FormFitAttrModelType parse(Form form) { |
||||
return LightTool.containNewFormFlag(form) ? NEW_FORM_FIT_ATTR_MODEL : PLAIN_FORM_FIT_ATTR_MODEL; |
||||
} |
||||
} |
@ -0,0 +1,163 @@
|
||||
package com.fr.design.report.fit; |
||||
|
||||
import com.fr.base.svg.SVGLoader; |
||||
import com.fr.design.gui.ibutton.UIRadioButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.gui.imenu.UIPopupMenu; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.report.fit.menupane.FitRadioGroup; |
||||
import com.fr.design.utils.gui.GUICoreUtils; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.report.fit.ReportFitAttr; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.JPopupMenu; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.FontMetrics; |
||||
import java.awt.Graphics; |
||||
import java.awt.Image; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.MouseAdapter; |
||||
import java.awt.event.MouseEvent; |
||||
|
||||
public class FormFitConfigPane extends ReportFitConfigPane { |
||||
private static final int ICON_OFFSET_X = 25; |
||||
private static final int ICON_OFFSET_Y = 3; |
||||
private static final int ICON_SIZE = 16; |
||||
private static final Image HOVER_IMAGE = SVGLoader.load("/com/fr/design/icon/icon_ec_default_fit.svg"); |
||||
private static final int DEFAULT_ITEM = 0; |
||||
|
||||
private static final int CUSTOM_ITEM = 1; |
||||
|
||||
public FormFitConfigPane(FitAttrModel fitAttrModel) { |
||||
this(fitAttrModel, false); |
||||
} |
||||
|
||||
public FormFitConfigPane(FitAttrModel fitAttrModel, boolean globalConfig) { |
||||
super(fitAttrModel, globalConfig); |
||||
} |
||||
|
||||
protected JPanel initECConfigPane() { |
||||
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
if (fitAttrModel.getFitTypeNames().length != 0) { |
||||
Component[] ecComponents = new Component[fitAttrModel.getFitTypeNames().length + 1]; |
||||
initRadioGroup(ecConfigRadioGroup, fitAttrModel.getFitName(), fitAttrModel.getFitTypeNames(), ecComponents); |
||||
jPanel.add(createSubAttrPane(ecComponents), BorderLayout.CENTER); |
||||
jPanel.add(createTipPane(), BorderLayout.SOUTH); |
||||
} |
||||
return jPanel; |
||||
} |
||||
|
||||
protected void initRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { |
||||
components[0] = new UILabel(name); |
||||
for (int i = 0; i < options.length; i++) { |
||||
if (options[i] != null) { |
||||
UIRadioButton fontFitRadio = ComparatorUtils.equals(options[i], Toolkit.i18nText("Fine-Designer_Fit-Default")) ? new UIRadioButtonWithIcon(options[i]) : new UIRadioButton(options[i]); |
||||
fitRadioGroup.add(fontFitRadio); |
||||
components[i + 1] = fontFitRadio; |
||||
} else { |
||||
components[i + 1] = null; |
||||
} |
||||
} |
||||
fitRadioGroup.addActionListener(getPreviewActionListener()); |
||||
} |
||||
|
||||
private class UIRadioButtonWithIcon extends UIRadioButton { |
||||
private final JPopupMenu popupMenu; |
||||
private NewFitPreviewPane ecFitPreviewPane; |
||||
|
||||
public UIRadioButtonWithIcon(String text) { |
||||
super(text); |
||||
popupMenu = this.createPopupMenu(); |
||||
initMouseListener(); |
||||
} |
||||
|
||||
private JPopupMenu createPopupMenu() { |
||||
UIPopupMenu uiPopupMenu = new UIPopupMenu() { |
||||
@Override |
||||
protected void paintBorder(Graphics g) { |
||||
|
||||
} |
||||
}; |
||||
uiPopupMenu.setLayout(new BorderLayout(0, 0)); |
||||
uiPopupMenu.setOpaque(false); |
||||
uiPopupMenu.add(ecFitPreviewPane = new NewFitPreviewPane(FitType.HORIZONTAL_FIT), BorderLayout.CENTER); |
||||
ecFitPreviewPane.setPreferredSize(new Dimension(300, 204)); |
||||
return uiPopupMenu; |
||||
} |
||||
|
||||
private void initMouseListener() { |
||||
this.addMouseListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseExited(MouseEvent e) { |
||||
super.mouseExited(e); |
||||
hidePreviewPane(); |
||||
} |
||||
}); |
||||
int defaultTextWidth = calculateStartX(); |
||||
this.addMouseMotionListener(new MouseAdapter() { |
||||
@Override |
||||
public void mouseMoved(MouseEvent e) { |
||||
super.mouseMoved(e); |
||||
if (new Rectangle(ICON_OFFSET_X + defaultTextWidth, ICON_OFFSET_Y, ICON_SIZE, ICON_SIZE).contains(e.getPoint())) { |
||||
showPreviewPane(e); |
||||
} else { |
||||
hidePreviewPane(); |
||||
} |
||||
|
||||
} |
||||
}); |
||||
} |
||||
|
||||
public void showPreviewPane(MouseEvent e) { |
||||
popupMenu.setVisible(true); |
||||
ecFitPreviewPane.refreshPreview(fontRadioGroup.isFontFit()); |
||||
GUICoreUtils.showPopupMenu(popupMenu, this, e.getX() + 10, e.getY() + 10); |
||||
} |
||||
|
||||
public void hidePreviewPane() { |
||||
if (popupMenu != null && popupMenu.isVisible()) { |
||||
popupMenu.setVisible(false); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
super.paint(g); |
||||
g.drawImage(HOVER_IMAGE, calculateStartX() + ICON_OFFSET_X, ICON_OFFSET_Y, null); |
||||
} |
||||
|
||||
private int calculateStartX() { |
||||
FontMetrics metrics = this.getFontMetrics(this.getFont()); |
||||
return metrics.stringWidth(this.getText()); |
||||
} |
||||
} |
||||
|
||||
private JPanel createTipPane() { |
||||
JPanel jPanel = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); |
||||
UILabel label1 = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_FIT_Config_Tip1")); |
||||
jPanel.add(label1); |
||||
label1.setForeground(Color.lightGray); |
||||
UILabel label2 = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_FIT_Config_Tip2")); |
||||
jPanel.add(label2); |
||||
label2.setForeground(Color.lightGray); |
||||
return jPanel; |
||||
} |
||||
|
||||
protected void refreshPreviewJPanel() { |
||||
previewJPanel.refreshPreview(fontRadioGroup.isFontFit()); |
||||
} |
||||
|
||||
protected void populateECConfigRadioGroup(int fitStateInPC) { |
||||
ecConfigRadioGroup.selectIndexButton(fitStateInPC == 0 ? DEFAULT_ITEM : CUSTOM_ITEM); |
||||
} |
||||
|
||||
protected void updateECConfigRadioGroup(ReportFitAttr reportFitAttr) { |
||||
reportFitAttr.setFitStateInPC(ecConfigRadioGroup.getSelectRadioIndex()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,79 @@
|
||||
package com.fr.design.report.fit; |
||||
|
||||
import com.fr.base.GraphHelper; |
||||
import com.fr.general.FRFont; |
||||
|
||||
import javax.swing.JPanel; |
||||
import java.awt.Color; |
||||
import java.awt.Dimension; |
||||
import java.awt.Font; |
||||
import java.awt.FontMetrics; |
||||
import java.awt.Graphics; |
||||
|
||||
|
||||
public class NewFitPreviewPane extends JPanel { |
||||
private boolean fitFont = false; |
||||
private FitType fitType = FitType.DOUBLE_FIT; |
||||
private static final Color DEFAULT_PAINT_COLOR = Color.decode("#419BF9"); |
||||
private static final int FIT_FONT_SIZE = 15; |
||||
private static final int NO_FIT_FONT_SIZE = 10; |
||||
private static final Dimension NO_FIT_CONTAINER_DIMENSION = new Dimension(230, 80); |
||||
|
||||
public NewFitPreviewPane(){ |
||||
|
||||
} |
||||
|
||||
public NewFitPreviewPane(FitType fitType){ |
||||
this.fitType = fitType; |
||||
} |
||||
|
||||
@Override |
||||
public void paint(Graphics g) { |
||||
super.paint(g); |
||||
g.setColor(Color.GRAY); |
||||
GraphHelper.drawRect(g, 1, 1, this.getWidth() - 2, this.getHeight() - 2); |
||||
g.setColor(DEFAULT_PAINT_COLOR); |
||||
FRFont textFont = FRFont.getInstance(FRFont.DEFAULT_FONTNAME, Font.PLAIN, fitFont ? FIT_FONT_SIZE : NO_FIT_FONT_SIZE); |
||||
g.setFont(textFont); |
||||
Dimension dimension = calculateCellDimension(); |
||||
GraphHelper.drawLine(g, 1, dimension.height, dimension.width * 2 - 1, dimension.height); |
||||
GraphHelper.drawLine(g, dimension.width, 1, dimension.width, dimension.height * 2 - 1); |
||||
GraphHelper.drawRect(g, 1, 1, dimension.width * 2 - 2, dimension.height * 2 - 2); |
||||
double startX = calculateTextDrawStartX(dimension.width, this.getFontMetrics(textFont), "text1"); |
||||
double startY = calculateTextDrawStartY(dimension.height); |
||||
GraphHelper.drawString(g, "text1", startX, startY); |
||||
GraphHelper.drawString(g, "text2", dimension.width + startX, startY); |
||||
GraphHelper.drawString(g, "text3", startX, dimension.height + startY); |
||||
GraphHelper.drawString(g, "text4", dimension.width + startX, dimension.height + startY); |
||||
} |
||||
|
||||
private Dimension calculateCellDimension() { |
||||
if (fitType == FitType.DOUBLE_FIT) { |
||||
return new Dimension(this.getWidth() / 2, this.getHeight() / 2); |
||||
} else if (fitType == FitType.NOT_FIT) { |
||||
return new Dimension(NO_FIT_CONTAINER_DIMENSION.width / 2, NO_FIT_CONTAINER_DIMENSION.height / 2); |
||||
} else { |
||||
return new Dimension(this.getWidth() / 2, NO_FIT_CONTAINER_DIMENSION.height / 2); |
||||
} |
||||
} |
||||
|
||||
private double calculateTextDrawStartX(int containerWidth, FontMetrics fontMetrics, String text) { |
||||
return (containerWidth - fontMetrics.stringWidth(text)) / 2.0D; |
||||
} |
||||
|
||||
private double calculateTextDrawStartY(int containerHeight) { |
||||
return containerHeight / 2.0D; |
||||
} |
||||
|
||||
public void refreshPreview(boolean fitFont, FitType fitType) { |
||||
this.fitFont = fitFont; |
||||
this.fitType = fitType; |
||||
repaint(); |
||||
} |
||||
|
||||
public void refreshPreview(boolean fitFont) { |
||||
this.fitFont = fitFont; |
||||
repaint(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,172 @@
|
||||
package com.fr.design.report.fit; |
||||
|
||||
import com.fr.design.gui.ibutton.UIRadioButton; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.DesignSizeI18nManager; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.report.fit.menupane.FitRadioGroup; |
||||
import com.fr.design.report.fit.menupane.FontRadioGroup; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.report.fit.ReportFitAttr; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.JPanel; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.FlowLayout; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
|
||||
import static com.fr.design.i18n.Toolkit.i18nText; |
||||
|
||||
public class ReportFitConfigPane extends JPanel { |
||||
public FontRadioGroup fontRadioGroup; |
||||
public FitRadioGroup ecConfigRadioGroup; |
||||
protected NewFitPreviewPane previewJPanel; |
||||
protected FitAttrModel fitAttrModel; |
||||
protected boolean globalConfig; |
||||
|
||||
|
||||
public ReportFitConfigPane(FitAttrModel fitAttrModel, boolean globalConfig) { |
||||
this.fitAttrModel = fitAttrModel; |
||||
this.globalConfig = globalConfig; |
||||
initComponent(); |
||||
} |
||||
|
||||
private void initComponent() { |
||||
JPanel contentJPanel = FRGUIPaneFactory.createVerticalFlowLayout_Pane(false, FlowLayout.LEFT, 0, 0); |
||||
this.add(contentJPanel); |
||||
fontRadioGroup = new FontRadioGroup(); |
||||
ecConfigRadioGroup = new FitRadioGroup(); |
||||
contentJPanel.add(initAttrJPanel()); |
||||
contentJPanel.add(initPreviewJPanel()); |
||||
} |
||||
|
||||
private JPanel initAttrJPanel() { |
||||
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
Component[] fontComponents = new Component[3]; |
||||
initRadioGroup(fontRadioGroup, i18nText("Fine-Designer_Fit-Font"), new String[]{i18nText("Fine-Designer_Fit"), i18nText("Fine-Designer_Fit-No")}, fontComponents); |
||||
jPanel.add(createSubAttrPane(fontComponents), BorderLayout.NORTH); |
||||
jPanel.add(initECConfigPane(), BorderLayout.CENTER); |
||||
return jPanel; |
||||
} |
||||
|
||||
protected JPanel initECConfigPane() { |
||||
JPanel jPanel = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
Component[] ecComponents = new Component[fitAttrModel.getFitTypeNames().length + 1]; |
||||
initRadioGroup(ecConfigRadioGroup, fitAttrModel.getFitName(), fitAttrModel.getFitTypeNames(), ecComponents); |
||||
jPanel.add(createSubAttrPane(ecComponents), BorderLayout.CENTER); |
||||
return jPanel; |
||||
} |
||||
|
||||
|
||||
protected JPanel createSubAttrPane(Component[] components) { |
||||
double[] rowSize = new double[]{20}; |
||||
double[] columnSize = new double[components.length]; |
||||
for (int i = 0; i < columnSize.length; i++) { |
||||
if (i == 0) { |
||||
columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.firstColumn").getWidth(); |
||||
} else { |
||||
columnSize[i] = DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.column").getWidth(); |
||||
} |
||||
} |
||||
|
||||
JPanel attrJPanel = TableLayoutHelper.createTableLayoutPane(new Component[][]{components}, rowSize, columnSize); |
||||
attrJPanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 10, 0)); |
||||
return attrJPanel; |
||||
} |
||||
|
||||
protected void initRadioGroup(FitRadioGroup fitRadioGroup, String name, String[] options, Component[] components) { |
||||
components[0] = new UILabel(name); |
||||
for (int i = 0; i < options.length; i++) { |
||||
|
||||
if (options[i] != null) { |
||||
UIRadioButton fontFitRadio = new UIRadioButton(options[i]); |
||||
fitRadioGroup.add(fontFitRadio); |
||||
components[i + 1] = fontFitRadio; |
||||
} else { |
||||
components[i + 1] = null; |
||||
} |
||||
} |
||||
fitRadioGroup.addActionListener(getPreviewActionListener()); |
||||
} |
||||
|
||||
protected ActionListener getPreviewActionListener() { |
||||
return new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
refreshPreviewJPanel(); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public void refreshPreviewJPanel(FitType fitType) { |
||||
previewJPanel.refreshPreview(fontRadioGroup.isFontFit(), fitType); |
||||
} |
||||
|
||||
protected void refreshPreviewJPanel() { |
||||
previewJPanel.refreshPreview(fontRadioGroup.isFontFit(), FitType.parse(updateBean())); |
||||
} |
||||
|
||||
private JPanel initPreviewJPanel() { |
||||
JPanel wrapperPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
previewJPanel = new NewFitPreviewPane(); |
||||
wrapperPane.add(previewJPanel, BorderLayout.CENTER); |
||||
int leftIndent = globalConfig ? (int) DesignSizeI18nManager.getInstance().i18nDimension("com.fr.design.report.fit.firstColumn").getWidth() : 0; |
||||
wrapperPane.setBorder(BorderFactory.createEmptyBorder(0, leftIndent, 0, 0)); |
||||
wrapperPane.setPreferredSize(new Dimension(300 + leftIndent, 204)); |
||||
return wrapperPane; |
||||
} |
||||
|
||||
|
||||
public void populateBean(ReportFitAttr ob) { |
||||
fontRadioGroup.selectIndexButton(ob.isFitFont() ? 0 : 1); |
||||
populateECConfigRadioGroup(ob.fitStateInPC()); |
||||
refreshPreviewJPanel(); |
||||
} |
||||
|
||||
protected void populateECConfigRadioGroup(int fitStateInPC){ |
||||
ecConfigRadioGroup.selectIndexButton(getOptionIndex(fitStateInPC)); |
||||
} |
||||
|
||||
|
||||
protected void updateECConfigRadioGroup(ReportFitAttr reportFitAttr){ |
||||
reportFitAttr.setFitStateInPC(getStateInPC(ecConfigRadioGroup.getSelectRadioIndex())); |
||||
} |
||||
|
||||
public ReportFitAttr updateBean() { |
||||
ReportFitAttr reportFitAttr = new ReportFitAttr(); |
||||
reportFitAttr.setFitFont(fontRadioGroup.isFontFit()); |
||||
updateECConfigRadioGroup(reportFitAttr); |
||||
return reportFitAttr; |
||||
} |
||||
|
||||
|
||||
protected int getStateInPC(int index) { |
||||
FitType[] fitTypes = fitAttrModel.getFitTypes(); |
||||
if (index > fitTypes.length - 1) { |
||||
return index; |
||||
} |
||||
return fitTypes[index].getState(); |
||||
} |
||||
|
||||
protected int getOptionIndex(int state) { |
||||
FitType[] fitTypes = fitAttrModel.getFitTypes(); |
||||
for (int i = 0; i < fitTypes.length; i++) { |
||||
if (ComparatorUtils.equals(state, fitTypes[i].getState())) { |
||||
return i; |
||||
} |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
super.setEnabled(enabled); |
||||
fontRadioGroup.setEnabled(enabled); |
||||
ecConfigRadioGroup.setEnabled(enabled); |
||||
} |
||||
|
||||
} |
After Width: | Height: | Size: 753 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 3.3 KiB |
@ -0,0 +1,47 @@
|
||||
{ |
||||
"Fine-Design_JSAPI_Public_Module": { |
||||
"Fine-Design_JSAPI_Public_Module_Global": { |
||||
"Fine-Design_JSAPI_Public_Module_Global_Universal": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Global_FR": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Global_FS": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Global_Mobile": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Widget": { |
||||
"Fine-Design_JSAPI_Public_Module_Widget_Get": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Widget_Universal": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Button_Widget_Peculiar": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Combobox_Widget_Peculiar": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Table": { |
||||
"Fine-Design_JSAPI_Public_Module_Table_Marquee": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Table_Scrollbar": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Table_Cell_Style": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Table_Row_Height_Col_Width": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Table_Cell_Value": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Table_Cell_Radius": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar": { |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Report_Page": { |
||||
"Fine-Design_JSAPI_Public_Module_Report_Page_Jump": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Report_Page_Number_Get": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Report_Export": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Cpt": { |
||||
"Fine-Design_JSAPI_Cpt_Page_Preview": { |
||||
"Fine-Design_JSAPI_Cpt_Page_Preview_Folding_Tree": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Cpt_Write_Preview": {}, |
||||
"Fine-Design_JSAPI_Cpt_View_Preview": { |
||||
"Fine-Design_JSAPI_Cpt_View_Preview_Report_Location": {} |
||||
} |
||||
}, |
||||
"Fine-Design_JSAPI_Form": { |
||||
"Fine-Design_JSAPI_Form_Component_Get": {}, |
||||
"Fine-Design_JSAPI_Form_Component_Universal": {}, |
||||
"Fine-Design_JSAPI_Form_Component_Tab": {} |
||||
} |
||||
} |
@ -0,0 +1,33 @@
|
||||
{ |
||||
"Fine-Design_JSAPI_Public_Module_Global_Universal": ["_g()", "getParameterContainer", "parameterCommit", "loadContentPane", "getPreviewType"], |
||||
"Fine-Design_JSAPI_Public_Module_Global_FR": [ "servletURL", "serverURL", "server", "fineServletURL", "SessionMgr.getSessionID", "showDialog", "closeDialog", |
||||
"doHyperlinkByGet", "doHyperlinkByPost", "doURLPrint", "Msg", "remoteEvaluate", "jsonEncode", "jsonDecode", |
||||
"ajax", "isEmpty", "isArray", "cellStr2ColumnRow", "columnRow2CellStr"], |
||||
"Fine-Design_JSAPI_Public_Module_Global_FS": ["signOut", "tabPane.closeActiveTab", "tabPane.addItem"], |
||||
"Fine-Design_JSAPI_Public_Module_Global_Mobile": ["location", "Mobile.getDeviceInfo"], |
||||
"Fine-Design_JSAPI_Public_Module_Widget_Get": ["this", "this.options.form", "getWidgetByName"], |
||||
"Fine-Design_JSAPI_Public_Module_Widget_Universal": ["getValue", "getText", "setValue", "visible", "invisible", "setVisible", "isVisible", "setEnable", "isEnabled", |
||||
"reset", "getType", "setWaterMark", "fireEvent", "setPopupStyle"], |
||||
"Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar":["setMaxAndMinDate"], |
||||
"Fine-Design_JSAPI_Public_Module_Button_Widget_Peculiar":["doClick"], |
||||
"Fine-Design_JSAPI_Public_Module_Combobox_Widget_Peculiar":["setName4Empty"], |
||||
"Fine-Design_JSAPI_Public_Module_Table_Marquee":["startMarquee", "stopMarquee"], |
||||
"Fine-Design_JSAPI_Public_Module_Table_Scrollbar":["setHScrollBarVisible", "setVScrollBarVisible"], |
||||
"Fine-Design_JSAPI_Public_Module_Table_Cell_Style":["addEffect"], |
||||
"Fine-Design_JSAPI_Public_Module_Table_Row_Height_Col_Width":["setRowHeight", "setColWidth"], |
||||
"Fine-Design_JSAPI_Public_Module_Table_Cell_Value":["getCellValue", "setCellValue"], |
||||
"Fine-Design_JSAPI_Public_Module_Table_Cell_Radius":["setCellRadius"], |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar":["toolBarFloat", "setStyle","getToolbar"], |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button":["changeFormat"], |
||||
"Fine-Design_JSAPI_Public_Module_Report_Page_Jump":["gotoPreviousPage", "gotoNextPage", "gotoLastPage", "gotoFirstPage", "gotoPage"], |
||||
"Fine-Design_JSAPI_Public_Module_Report_Page_Number_Get":["getCurrentPageIndex", "getReportTotalPage", "currentPageIndex", "reportTotalPage"], |
||||
"Fine-Design_JSAPI_Public_Module_Report_Export":["exportReportToExcel", "exportReportToImage", "exportReportToPDF", "exportReportToWord"], |
||||
"Fine-Design_JSAPI_Cpt_Page_Preview_Folding_Tree":["expandNodeLayer", "collapseNodeLayer", "expandAllNodeLayer", "collapseAllNodeLayer"], |
||||
"Fine-Design_JSAPI_Cpt_Write_Preview":["getWidgetByCell", "appendReportRC", "appendReportRow", |
||||
"deleteReportRC", "deleteRows", "refreshAllSheets", "loadSheetByIndex", "loadSheetByName", "isDirtyPage", |
||||
"isAutoStash", "writeReport", "verifyAndWriteReport", "verifyReport", "importExcel", "importExcel_Clean", |
||||
"importExcel_Append", "importExcel_Cover", "stash", "clear"], |
||||
"Fine-Design_JSAPI_Cpt_View_Preview_Report_Location":["centerReport"], |
||||
"Fine-Design_JSAPI_Form_Component_Get":["getAllWidgets"], |
||||
"Fine-Design_JSAPI_Form_Component_Tab":["showCardByIndex", "showCardByIndex", "getShowIndex", "setTitleVisible"] |
||||
} |
@ -0,0 +1,31 @@
|
||||
package com.fr.design.javascript.jsapi; |
||||
|
||||
import java.util.List; |
||||
import javax.swing.tree.DefaultMutableTreeNode; |
||||
import junit.framework.TestCase; |
||||
|
||||
public class JSAPITreeHelperTest extends TestCase { |
||||
public void testGetName(){ |
||||
List<String> names = JSAPITreeHelper.getNames("Fine-Design_JSAPI_Public_Module_Toolbar"); |
||||
assertEquals(names.size(),4); |
||||
assertTrue(names.contains( "toolBarFloat")); |
||||
assertTrue(names.contains( "setStyle")); |
||||
assertTrue(names.contains( "getToolbar")); |
||||
assertTrue(names.contains( "changeFormat")); |
||||
List<String> allNames = JSAPITreeHelper.getAllNames(); |
||||
assertEquals(allNames.size(),16); |
||||
} |
||||
|
||||
public void testGetDirectCategory(){ |
||||
String directCategory = JSAPITreeHelper.getDirectCategory("_g()"); |
||||
assertEquals(directCategory,"Fine-Design_JSAPI_Public_Module_Global_Universal"); |
||||
directCategory = JSAPITreeHelper.getDirectCategory("showCardByIndex"); |
||||
assertEquals(directCategory,"Fine-Design_JSAPI_Form_Component_Tab"); |
||||
} |
||||
|
||||
public void testCreateJSAPITree(){ |
||||
DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode(); |
||||
JSAPITreeHelper.createJSAPITree(rootNode); |
||||
assertEquals(2,rootNode.getChildCount()); |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
{ |
||||
"Fine-Design_JSAPI_Public_Module": { |
||||
"Fine-Design_JSAPI_Public_Module_Global": { |
||||
"Fine-Design_JSAPI_Public_Module_Global_Universal": {}, |
||||
"Fine-Design_JSAPI_Public_Module_Global_Mobile": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Widget": { |
||||
"Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar": {} |
||||
}, |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar": { |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button": {} |
||||
} |
||||
}, |
||||
"Fine-Design_JSAPI_Form": { |
||||
"Fine-Design_JSAPI_Form_Component_Tab": {} |
||||
} |
||||
} |
@ -0,0 +1,8 @@
|
||||
{ |
||||
"Fine-Design_JSAPI_Public_Module_Global_Universal": ["_g()", "getParameterContainer", "parameterCommit", "loadContentPane", "getPreviewType"], |
||||
"Fine-Design_JSAPI_Public_Module_Global_Mobile": ["location", "Mobile.getDeviceInfo"], |
||||
"Fine-Design_JSAPI_Public_Module_Date_Widget_Peculiar":["setMaxAndMinDate"], |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar":["toolBarFloat", "setStyle","getToolbar"], |
||||
"Fine-Design_JSAPI_Public_Module_Toolbar_Email_Button":["changeFormat"], |
||||
"Fine-Design_JSAPI_Form_Component_Tab":["showCardByIndex", "showCardByIndex", "getShowIndex", "setTitleVisible"] |
||||
} |
@ -0,0 +1,117 @@
|
||||
package com.fr.van.chart.designer.component; |
||||
|
||||
import com.fr.chart.chartattr.Plot; |
||||
import com.fr.design.gui.frpane.UINumberDragPaneWithPercent; |
||||
import com.fr.design.gui.ibutton.UIButtonGroup; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.mainframe.chart.gui.ColorSelectBoxWithOutTransparent; |
||||
import com.fr.plugin.chart.gantt.VanChartGanttPlot; |
||||
import com.fr.van.chart.designer.TableLayout4VanChartHelper; |
||||
|
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import javax.swing.event.ChangeEvent; |
||||
import javax.swing.event.ChangeListener; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Color; |
||||
import java.awt.Component; |
||||
|
||||
public class VanChartGanttTimeLinePane extends JPanel { |
||||
private UIButtonGroup<String> switchButton; |
||||
private ColorSelectBoxWithOutTransparent colorSelect; |
||||
private UINumberDragPaneWithPercent opacity; |
||||
|
||||
private JPanel centerPane; |
||||
|
||||
public VanChartGanttTimeLinePane() { |
||||
this.setLayout(new BorderLayout()); |
||||
this.add(createSwitchButtonPane(), BorderLayout.NORTH); |
||||
this.add(createCenterPane(), BorderLayout.CENTER); |
||||
} |
||||
|
||||
private JPanel createSwitchButtonPane() { |
||||
double[] columnSize = {TableLayout.PREFERRED, TableLayout.FILL}; |
||||
double[] rowSize = {TableLayout.PREFERRED, TableLayout.PREFERRED}; |
||||
String[] array = new String[]{Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Not_Show"), Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Show")}; |
||||
switchButton = new UIButtonGroup<>(array); |
||||
switchButton.addChangeListener(new ChangeListener() { |
||||
@Override |
||||
public void stateChanged(ChangeEvent e) { |
||||
setCenterPaneVisibility(); |
||||
} |
||||
}); |
||||
UILabel text = new UILabel(Toolkit.i18nText("Fine-Design_Chart_Guide_Line_Current_Line"), SwingConstants.LEFT); |
||||
return TableLayout4VanChartHelper.createGapTableLayoutPane(new Component[][] { |
||||
new Component[]{null, null}, |
||||
new Component[] {text, switchButton} |
||||
}, rowSize, columnSize); |
||||
} |
||||
|
||||
private JPanel createCenterPane() { |
||||
double[] columnSize = {TableLayout.FILL, TableLayout4VanChartHelper.EDIT_AREA_WIDTH}; |
||||
double[] rowSize = {TableLayout.PREFERRED, TableLayout.PREFERRED, TableLayout.PREFERRED}; |
||||
|
||||
colorSelect = new ColorSelectBoxWithOutTransparent(100); |
||||
opacity = new UINumberDragPaneWithPercent(0, 100); |
||||
|
||||
centerPane = TableLayout4VanChartHelper.createGapTableLayoutPane(new Component[][] { |
||||
new Component[]{null, null}, |
||||
new Component[] {new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), colorSelect}, |
||||
new Component[] {new UILabel(Toolkit.i18nText("Fine-Design_Report_Alpha")), opacity} |
||||
}, rowSize, columnSize); |
||||
|
||||
centerPane.setVisible(false); |
||||
|
||||
return centerPane; |
||||
} |
||||
|
||||
public void populateBean(Plot plot) { |
||||
if (plot instanceof VanChartGanttPlot) { |
||||
VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; |
||||
setShowTimeLine(ganttPlot.isShowTimeLine()); |
||||
setTimeLineColor(ganttPlot.getTimeLineColor()); |
||||
setTimeLineOpacity(ganttPlot.getTimeLineOpacity()); |
||||
|
||||
centerPane.setVisible(ganttPlot.isShowTimeLine()); |
||||
} |
||||
} |
||||
|
||||
public void updateBean(Plot plot) { |
||||
if (plot instanceof VanChartGanttPlot) { |
||||
VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; |
||||
ganttPlot.setShowTimeLine(isShowTimeLine()); |
||||
ganttPlot.setTimeLineColor(getTimeLineColor()); |
||||
ganttPlot.setTimeLineOpacity(getTimeLineOpacity()); |
||||
} |
||||
} |
||||
|
||||
private void setCenterPaneVisibility() { |
||||
centerPane.setVisible(switchButton.getSelectedIndex() == 1); |
||||
} |
||||
|
||||
public boolean isShowTimeLine() { |
||||
return switchButton.getSelectedIndex() == 1; |
||||
} |
||||
|
||||
public void setShowTimeLine(boolean showTimeLine) { |
||||
switchButton.setSelectedIndex(showTimeLine ? 1 : 0); |
||||
} |
||||
|
||||
public Color getTimeLineColor() { |
||||
return colorSelect.getSelectObject(); |
||||
} |
||||
|
||||
public void setTimeLineColor(Color timeLineColor) { |
||||
colorSelect.setSelectObject(timeLineColor); |
||||
} |
||||
|
||||
public double getTimeLineOpacity() { |
||||
return opacity.updateBean(); |
||||
} |
||||
|
||||
public void setTimeLineOpacity(double timeLineOpacity) { |
||||
opacity.populateBean(timeLineOpacity); |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
package com.fr.van.chart.designer.style.background; |
||||
|
||||
import com.fr.chart.chartattr.Plot; |
||||
import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; |
||||
import com.fr.van.chart.designer.style.VanChartStylePane; |
||||
|
||||
public class VanChartGantAreaPane extends VanChartAreaPane { |
||||
public VanChartGantAreaPane(Plot plot, VanChartStylePane parent) { |
||||
super(plot, parent); |
||||
} |
||||
|
||||
protected void initPlotPane(boolean b, AbstractAttrNoScrollPane parent) { |
||||
plotPane = new VanChartGantPlotAreaBackgroundPane(parent); |
||||
} |
||||
} |
@ -0,0 +1,102 @@
|
||||
package com.fr.van.chart.designer.style.background; |
||||
|
||||
import com.fr.chart.chartattr.Chart; |
||||
import com.fr.chart.chartattr.Plot; |
||||
import com.fr.design.gui.frpane.AbstractAttrNoScrollPane; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.TableLayout; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.chart.gui.ColorSelectBoxWithOutTransparent; |
||||
import com.fr.plugin.chart.gantt.VanChartGanttPlot; |
||||
import com.fr.van.chart.designer.TableLayout4VanChartHelper; |
||||
|
||||
import javax.swing.JPanel; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
|
||||
public class VanChartGantPlotAreaBackgroundPane extends VanChartAreaBackgroundPane { |
||||
private ColorSelectBoxWithOutTransparent axisColorPane; |
||||
private ColorSelectBoxWithOutTransparent contentColorPane; |
||||
|
||||
public VanChartGantPlotAreaBackgroundPane(AbstractAttrNoScrollPane parent) { |
||||
super(true, parent); |
||||
} |
||||
|
||||
@Override |
||||
protected JPanel createContentPane() { |
||||
JPanel contentPane = new JPanel(new BorderLayout()); |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] columnSize = {f}; |
||||
double[] rowSize = {p, p}; |
||||
Component[][] components = new Component[][]{ |
||||
new Component[]{createAxisBorderPane()}, |
||||
new Component[]{createContentBorderPane()} |
||||
}; |
||||
|
||||
contentPane.add(TableLayoutHelper.createTableLayoutPane(components, rowSize, columnSize), BorderLayout.CENTER); |
||||
return contentPane; |
||||
} |
||||
|
||||
@Override |
||||
public void updateBean(Chart chart) { |
||||
if (chart == null) { |
||||
chart = new Chart(); |
||||
} |
||||
|
||||
Plot plot = chart.getPlot(); |
||||
if (plot instanceof VanChartGanttPlot) { |
||||
VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; |
||||
ganttPlot.setAxisBorderColor(axisColorPane.getSelectObject()); |
||||
ganttPlot.setContentBorderColor(contentColorPane.getSelectObject()); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void populateBean(Chart chart) { |
||||
if (chart == null) { |
||||
chart = new Chart(); |
||||
} |
||||
|
||||
Plot plot = chart.getPlot(); |
||||
if (plot instanceof VanChartGanttPlot) { |
||||
VanChartGanttPlot ganttPlot = (VanChartGanttPlot) plot; |
||||
axisColorPane.setSelectObject(ganttPlot.getAxisBorderColor()); |
||||
contentColorPane.setSelectObject(ganttPlot.getContentBorderColor()); |
||||
} |
||||
} |
||||
|
||||
private JPanel createAxisBorderPane() { |
||||
axisColorPane = new ColorSelectBoxWithOutTransparent(100); |
||||
return TableLayout4VanChartHelper.createExpandablePaneWithTitle( |
||||
Toolkit.i18nText("Fine-Design_Chart_Gant_Axis_Border"), |
||||
createBorderPane(axisColorPane) |
||||
); |
||||
} |
||||
|
||||
private JPanel createContentBorderPane() { |
||||
contentColorPane = new ColorSelectBoxWithOutTransparent(100); |
||||
return TableLayout4VanChartHelper.createExpandablePaneWithTitle( |
||||
Toolkit.i18nText("Fine-Design_Chart_Gant_Content_Border"), |
||||
createBorderPane(contentColorPane) |
||||
); |
||||
} |
||||
|
||||
private JPanel createBorderPane(ColorSelectBoxWithOutTransparent colorPane) { |
||||
double p = TableLayout.PREFERRED; |
||||
double f = TableLayout.FILL; |
||||
double[] columnSize = {f, TableLayout4VanChartHelper.EDIT_AREA_WIDTH}; |
||||
double[] rowSize = {p, p}; |
||||
|
||||
Component[][] components = new Component[][]{ |
||||
new Component[]{null, null}, |
||||
new Component[]{ |
||||
new UILabel(Toolkit.i18nText("Fine-Design_Chart_Color")), |
||||
colorPane |
||||
} |
||||
}; |
||||
|
||||
return TableLayout4VanChartHelper.createGapTableLayoutPane(components, rowSize, columnSize); |
||||
} |
||||
} |
@ -0,0 +1,9 @@
|
||||
package com.fr.design.designer.beans.events; |
||||
|
||||
import java.util.EventListener; |
||||
|
||||
public interface AddingWidgetListener extends EventListener { |
||||
void beforeAdded(); |
||||
|
||||
void afterAdded(boolean addResult); |
||||
} |
@ -0,0 +1,54 @@
|
||||
package com.fr.design.designer.beans.events; |
||||
|
||||
import com.fr.general.ComparatorUtils; |
||||
|
||||
import javax.swing.SwingUtilities; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class AddingWidgetListenerTable { |
||||
protected List<AddingWidgetListener> listeners = new ArrayList<>(); |
||||
|
||||
public AddingWidgetListenerTable() { |
||||
|
||||
} |
||||
|
||||
public void addListener(AddingWidgetListener listener) { |
||||
if (listener == null) { |
||||
return; |
||||
} |
||||
for (int i = 0; i < listeners.size(); i++) { |
||||
if (ComparatorUtils.equals(listener, listeners.get(i))) { |
||||
listeners.set(i, listener); |
||||
return; |
||||
} |
||||
} |
||||
listeners.add(listener); |
||||
} |
||||
|
||||
public void beforeAdded() { |
||||
for (final AddingWidgetListener listener : listeners) { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
listener.beforeAdded(); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
public void afterAdded(boolean addResult) { |
||||
for (final AddingWidgetListener listener : listeners) { |
||||
SwingUtilities.invokeLater(new Runnable() { |
||||
@Override |
||||
public void run() { |
||||
listener.afterAdded(addResult); |
||||
} |
||||
}); |
||||
} |
||||
} |
||||
|
||||
public void clearListeners() { |
||||
listeners.clear(); |
||||
} |
||||
} |
@ -0,0 +1,98 @@
|
||||
package com.fr.design.designer.beans.models; |
||||
|
||||
import com.fr.design.designer.beans.LayoutAdapter; |
||||
import com.fr.design.designer.creator.XCreator; |
||||
import com.fr.design.designer.creator.XLayoutContainer; |
||||
import com.fr.design.mainframe.FormDesigner; |
||||
|
||||
import java.awt.event.MouseEvent; |
||||
|
||||
public class DraggingModel { |
||||
private FormDesigner designer; |
||||
private XCreator creator; |
||||
private MouseEvent startDragEvent; |
||||
private MouseEvent currentDragEvent; |
||||
private int creatorLeftTopX = -999; // 隐藏
|
||||
private int creatorLeftTopY = -999; // 隐藏
|
||||
private boolean dragNewWidget; // 是否正在拖拽一个新的组件下来
|
||||
|
||||
public DraggingModel() { |
||||
|
||||
} |
||||
|
||||
public DraggingModel designer(FormDesigner designer) { |
||||
this.designer = designer; |
||||
return this; |
||||
} |
||||
|
||||
public DraggingModel startDragEvent(MouseEvent startDragEvent) { |
||||
this.startDragEvent = startDragEvent; |
||||
return this; |
||||
} |
||||
|
||||
public DraggingModel currentDragEvent(MouseEvent dragEvent) { |
||||
this.currentDragEvent = dragEvent; |
||||
return this; |
||||
} |
||||
|
||||
public DraggingModel creator(XCreator creator) { |
||||
this.creator = creator; |
||||
return this; |
||||
} |
||||
|
||||
public DraggingModel dragNewWidget(boolean dragNewWidget) { |
||||
this.dragNewWidget = dragNewWidget; |
||||
return this; |
||||
} |
||||
|
||||
public FormDesigner getDesigner() { |
||||
return designer; |
||||
} |
||||
|
||||
public MouseEvent getStartDragEvent() { |
||||
return startDragEvent; |
||||
} |
||||
|
||||
public MouseEvent getCurrentDragEvent() { |
||||
return currentDragEvent; |
||||
} |
||||
|
||||
public XCreator getCreator() { |
||||
return creator; |
||||
} |
||||
|
||||
/** |
||||
* 获取被拖拽组件当前随着鼠标移动时应当所在的左上角横坐标 |
||||
* |
||||
* @return |
||||
*/ |
||||
public int getCreatorLeftTopX() { |
||||
return creatorLeftTopX; |
||||
} |
||||
|
||||
/** |
||||
* 获取被拖拽组件当前随着鼠标移动时应当所在的左上角纵坐标 |
||||
* |
||||
* @return |
||||
*/ |
||||
public int getCreatorLeftTopY() { |
||||
return creatorLeftTopY; |
||||
} |
||||
|
||||
public boolean isDragNewWidget() { |
||||
return dragNewWidget; |
||||
} |
||||
|
||||
public void moveTo(int x, int y) { |
||||
XLayoutContainer container = designer.getDraggingHotspotLayout(); |
||||
LayoutAdapter adapter = container.getLayoutAdapter(); |
||||
|
||||
creatorLeftTopX = x - adapter.getDragSize(creator).width / 2; |
||||
creatorLeftTopY = y - adapter.getDragSize(creator).height / 2; |
||||
} |
||||
|
||||
public void reset() { |
||||
creatorLeftTopX = -creator.getWidth(); |
||||
creatorLeftTopY = -creator.getHeight(); |
||||
} |
||||
} |
@ -0,0 +1,85 @@
|
||||
package com.fr.design.fit; |
||||
|
||||
import com.fr.design.actions.JTemplateAction; |
||||
import com.fr.design.beans.BasicBeanPane; |
||||
import com.fr.design.dialog.DialogActionAdapter; |
||||
import com.fr.design.dialog.UIDialog; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.mainframe.DesignerContext; |
||||
import com.fr.design.mainframe.JForm; |
||||
import com.fr.design.mainframe.JTemplate; |
||||
import com.fr.design.menu.MenuKeySet; |
||||
import com.fr.design.report.fit.FormFitAttrModelType; |
||||
import com.fr.form.main.Form; |
||||
import com.fr.report.fit.FitProvider; |
||||
import com.fr.report.fit.ReportFitAttr; |
||||
|
||||
import javax.swing.KeyStroke; |
||||
import java.awt.Dimension; |
||||
import java.awt.event.ActionEvent; |
||||
|
||||
public class FormFitAttrAction extends JTemplateAction { |
||||
private static final MenuKeySet REPORT_FIT_ATTR = new MenuKeySet() { |
||||
@Override |
||||
public char getMnemonic() { |
||||
return 'T'; |
||||
} |
||||
|
||||
@Override |
||||
public String getMenuName() { |
||||
return Toolkit.i18nText("Fine-Designer_PC_Fit_Attr"); |
||||
} |
||||
|
||||
@Override |
||||
public KeyStroke getKeyStroke() { |
||||
return null; |
||||
} |
||||
}; |
||||
|
||||
public FormFitAttrAction(JTemplate jTemplate) { |
||||
super(jTemplate); |
||||
initMenuStyle(); |
||||
} |
||||
|
||||
private void initMenuStyle() { |
||||
this.setMenuKeySet(REPORT_FIT_ATTR); |
||||
this.setName(getMenuKeySet().getMenuKeySetName() + "..."); |
||||
this.setMnemonic(getMenuKeySet().getMnemonic()); |
||||
this.setSmallIcon("/com/fr/design/images/reportfit/fit"); |
||||
} |
||||
|
||||
/** |
||||
* Action触发事件 |
||||
* |
||||
* @param e 事件 |
||||
*/ |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
final JTemplate jwb = getEditingComponent(); |
||||
if (jwb == null || !(jwb.getTarget() instanceof Form)) { |
||||
return; |
||||
} |
||||
JForm jForm = (JForm) jwb; |
||||
Form wbTpl = jForm.getTarget(); |
||||
ReportFitAttr fitAttr = wbTpl.getReportFitAttr(); |
||||
FormFitAttrPane formFitAttrPane = new FormFitAttrPane(jForm, FormFitAttrModelType.parse(wbTpl)); |
||||
showReportFitDialog(fitAttr, jwb, wbTpl, formFitAttrPane); |
||||
} |
||||
|
||||
private void showReportFitDialog(ReportFitAttr fitAttr, final JTemplate jwb, final FitProvider wbTpl, final BasicBeanPane<ReportFitAttr> attrPane) { |
||||
attrPane.populateBean(fitAttr); |
||||
UIDialog dialog = attrPane.showWindowWithCustomSize(DesignerContext.getDesignerFrame(), new DialogActionAdapter() { |
||||
@Override |
||||
public void doOk() { |
||||
fireEditingOk(jwb, wbTpl, attrPane.updateBean(), fitAttr); |
||||
} |
||||
}, new Dimension(660, 600)); |
||||
dialog.setVisible(true); |
||||
} |
||||
|
||||
private void fireEditingOk(final JTemplate jwb, final FitProvider wbTpl, ReportFitAttr newReportFitAttr, ReportFitAttr oldReportFitAttr) { |
||||
wbTpl.setReportFitAttr(newReportFitAttr); |
||||
jwb.fireTargetModified(); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,377 @@
|
||||
package com.fr.design.fit; |
||||
|
||||
import com.fr.design.beans.BasicBeanPane; |
||||
import com.fr.design.designer.IntervalConstants; |
||||
import com.fr.design.designer.creator.XCreator; |
||||
import com.fr.design.designer.creator.XLayoutContainer; |
||||
import com.fr.design.designer.creator.XOccupiedLayout; |
||||
import com.fr.design.designer.creator.XWAbsoluteBodyLayout; |
||||
import com.fr.design.designer.creator.XWFitLayout; |
||||
import com.fr.design.designer.creator.XWScaleLayout; |
||||
import com.fr.design.designer.properties.items.FRLayoutTypeItems; |
||||
import com.fr.design.designer.properties.items.Item; |
||||
import com.fr.design.dialog.FineJOptionPane; |
||||
import com.fr.design.gui.icombobox.UIComboBox; |
||||
import com.fr.design.gui.ilable.UILabel; |
||||
import com.fr.design.i18n.Toolkit; |
||||
import com.fr.design.layout.FRGUIPaneFactory; |
||||
import com.fr.design.layout.TableLayoutHelper; |
||||
import com.fr.design.mainframe.FormDesigner; |
||||
import com.fr.design.mainframe.FormSelectionUtils; |
||||
import com.fr.design.mainframe.JForm; |
||||
import com.fr.design.mainframe.WidgetPropertyPane; |
||||
import com.fr.design.report.fit.FitType; |
||||
import com.fr.design.report.fit.FormFitAttrModelType; |
||||
import com.fr.design.report.fit.FormFitConfigPane; |
||||
import com.fr.design.report.fit.ReportFitConfigPane; |
||||
import com.fr.design.widget.FRWidgetFactory; |
||||
import com.fr.form.main.Form; |
||||
import com.fr.form.ui.Widget; |
||||
import com.fr.form.ui.container.WAbsoluteBodyLayout; |
||||
import com.fr.form.ui.container.WAbsoluteLayout; |
||||
import com.fr.form.ui.container.WBodyLayoutType; |
||||
import com.fr.form.ui.container.WFitLayout; |
||||
import com.fr.form.ui.container.WSortLayout; |
||||
import com.fr.general.ComparatorUtils; |
||||
import com.fr.general.act.BorderPacker; |
||||
import com.fr.log.FineLoggerFactory; |
||||
import com.fr.report.fit.ReportFitAttr; |
||||
|
||||
import javax.swing.BorderFactory; |
||||
import javax.swing.DefaultComboBoxModel; |
||||
import javax.swing.JPanel; |
||||
import javax.swing.SwingConstants; |
||||
import java.awt.BorderLayout; |
||||
import java.awt.Component; |
||||
import java.awt.Dimension; |
||||
import java.awt.Rectangle; |
||||
import java.awt.event.ActionEvent; |
||||
import java.awt.event.ActionListener; |
||||
import java.awt.event.ItemEvent; |
||||
import java.awt.event.ItemListener; |
||||
|
||||
import static com.fr.design.i18n.Toolkit.i18nText; |
||||
import static javax.swing.JOptionPane.*; |
||||
|
||||
public class FormFitAttrPane extends BasicBeanPane<ReportFitAttr> { |
||||
|
||||
private UIComboBox layoutComboBox; |
||||
private UIComboBox scaleComboBox; |
||||
private FormFitAttrModelType fitAttrModelType; |
||||
|
||||
protected UIComboBox itemChoose; |
||||
|
||||
private JForm jForm; |
||||
private ReportFitConfigPane fitConfigPane; |
||||
|
||||
public FormFitAttrPane(JForm jForm, FormFitAttrModelType fitAttrModelType) { |
||||
this.fitAttrModelType = fitAttrModelType; |
||||
this.jForm = jForm; |
||||
initComponents(); |
||||
} |
||||
|
||||
|
||||
private void initComponents() { |
||||
this.setLayout(FRGUIPaneFactory.createBorderLayout()); |
||||
this.setBorder(BorderFactory.createEmptyBorder(12, 5, 0, 5)); |
||||
this.add(createReportFitSettingPane(), BorderLayout.CENTER); |
||||
this.add(createReportLayoutSettingPane(), BorderLayout.NORTH); |
||||
|
||||
} |
||||
|
||||
|
||||
private JPanel createReportLayoutSettingPane() { |
||||
JPanel jPanel = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Layout")); |
||||
jPanel.add(createAreaScalePane(), BorderLayout.CENTER); |
||||
jPanel.setPreferredSize(new Dimension(640, 84)); |
||||
return jPanel; |
||||
} |
||||
|
||||
protected String[] getItemNames() { |
||||
return new String[]{Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings"), |
||||
Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")}; |
||||
} |
||||
|
||||
|
||||
private JPanel createReportFitSettingPane() { |
||||
JPanel jPanel = FRGUIPaneFactory.createTitledBorderPane(Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Content_Attr")); |
||||
JPanel contentPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
jPanel.add(contentPane, BorderLayout.CENTER); |
||||
UILabel label = new UILabel(Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Settings")); |
||||
label.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0)); |
||||
contentPane.add(label, BorderLayout.WEST); |
||||
label.setPreferredSize(new Dimension(100, 0)); |
||||
label.setVerticalAlignment(SwingConstants.TOP); |
||||
itemChoose = new UIComboBox(getItemNames()); |
||||
itemChoose.setPreferredSize(new Dimension(160, 20)); |
||||
Form form = jForm.getTarget(); |
||||
itemChoose.addItemListener(new ItemListener() { |
||||
@Override |
||||
public void itemStateChanged(ItemEvent e) { |
||||
if (e.getStateChange() == ItemEvent.SELECTED) { |
||||
if (isTemplateSingleSet()) { |
||||
if (form != null) { |
||||
ReportFitAttr fitAttr = form.getReportFitAttr(); |
||||
populate(fitAttr); |
||||
} |
||||
} else { |
||||
populate(fitAttrModelType.getFitAttrModel().getGlobalReportFitAttr()); |
||||
} |
||||
} |
||||
} |
||||
}); |
||||
JPanel centerPane = FRGUIPaneFactory.createVerticalFlowLayout_S_Pane(true); |
||||
centerPane.add(itemChoose); |
||||
centerPane.add(fitConfigPane = new FormFitConfigPane(this.fitAttrModelType.getFitAttrModel())); |
||||
contentPane.add(centerPane, BorderLayout.CENTER); |
||||
return jPanel; |
||||
} |
||||
|
||||
public void populate(ReportFitAttr reportFitAttr) { |
||||
if (reportFitAttr == null) { |
||||
reportFitAttr = fitAttrModelType.getFitAttrModel().getGlobalReportFitAttr(); |
||||
} |
||||
|
||||
this.setEnabled(isTemplateSingleSet()); |
||||
fitConfigPane.populateBean(reportFitAttr); |
||||
} |
||||
|
||||
|
||||
public ReportFitAttr updateBean() { |
||||
updateLayoutType(); |
||||
if (!isTemplateSingleSet()) { |
||||
return null; |
||||
} else { |
||||
return fitConfigPane.updateBean(); |
||||
} |
||||
} |
||||
|
||||
private void updateLayoutType() { |
||||
XLayoutContainer xLayoutContainer = this.jForm.getRootComponent(); |
||||
if (xLayoutContainer == null || !xLayoutContainer.acceptType(XWFitLayout.class)) { |
||||
return; |
||||
} |
||||
XWFitLayout xwFitLayout = (XWFitLayout) xLayoutContainer; |
||||
WFitLayout wFitLayout = xwFitLayout.toData(); |
||||
int state = layoutComboBox.getSelectedIndex(); |
||||
WBodyLayoutType selectType = WBodyLayoutType.parse(state); |
||||
if (selectType != wFitLayout.getBodyLayoutType()) { |
||||
wFitLayout.setLayoutType(selectType); |
||||
//从自适应布局切换到绝对布局
|
||||
if (selectType == WBodyLayoutType.ABSOLUTE) { |
||||
switchLayoutFromFit2Absolute(xwFitLayout); |
||||
} else { |
||||
//从绝对布局切换到自适应布局
|
||||
switchLayoutFromAbsolute2Fit(xwFitLayout); |
||||
} |
||||
} |
||||
wFitLayout.setCompatibleScaleAttr(fitAttrModelType.parseScaleAttrFromShowIndex(this.scaleComboBox.getSelectedIndex(), wFitLayout.getBodyLayoutType())); |
||||
} |
||||
|
||||
|
||||
private void switchLayoutFromFit2Absolute(XWFitLayout xWFitLayout) { |
||||
try { |
||||
WFitLayout layout = xWFitLayout.toData(); |
||||
WAbsoluteBodyLayout wAbsoluteBodyLayout = new WAbsoluteBodyLayout("body"); |
||||
wAbsoluteBodyLayout.setCompState(WAbsoluteLayout.STATE_FIXED); |
||||
// 切换布局类型时,保留body背景样式
|
||||
wAbsoluteBodyLayout.setBorderStyleFollowingTheme(layout.isBorderStyleFollowingTheme()); |
||||
wAbsoluteBodyLayout.setBorderStyle((BorderPacker) (layout.getBorderStyle().clone())); |
||||
Component[] components = xWFitLayout.getComponents(); |
||||
Rectangle[] backupBounds = getBackupBoundsFromFitLayout(xWFitLayout); |
||||
xWFitLayout.removeAll(); |
||||
layout.resetStyle(); |
||||
XWAbsoluteBodyLayout xwAbsoluteBodyLayout = xWFitLayout.getBackupParent() == null ? new XWAbsoluteBodyLayout(wAbsoluteBodyLayout, new Dimension(0, 0)) : (XWAbsoluteBodyLayout) xWFitLayout.getBackupParent(); |
||||
xWFitLayout.setFixLayout(false); |
||||
xWFitLayout.getLayoutAdapter().addBean(xwAbsoluteBodyLayout, 0, 0); |
||||
for (int i = 0; i < components.length; i++) { |
||||
XCreator xCreator = (XCreator) components[i]; |
||||
xCreator.setBounds(backupBounds[i]); |
||||
//部分控件被ScaleLayout包裹着,绝对布局里面要放出来
|
||||
if (xCreator.acceptType(XWScaleLayout.class)) { |
||||
if (xCreator.getComponentCount() > 0 && ((XCreator) xCreator.getComponent(0)).shouldScaleCreator()) { |
||||
Component component = xCreator.getComponent(0); |
||||
component.setBounds(xCreator.getBounds()); |
||||
} |
||||
} |
||||
if (!xCreator.acceptType(XOccupiedLayout.class)) { |
||||
xwAbsoluteBodyLayout.add(xCreator); |
||||
} |
||||
|
||||
} |
||||
copyLayoutAttr(layout, xwAbsoluteBodyLayout.toData()); |
||||
xWFitLayout.setBackupParent(xwAbsoluteBodyLayout); |
||||
FormDesigner formDesigner = WidgetPropertyPane.getInstance().getEditingFormDesigner(); |
||||
formDesigner.getSelectionModel().setSelectedCreators( |
||||
FormSelectionUtils.rebuildSelection(xWFitLayout, new Widget[]{wAbsoluteBodyLayout})); |
||||
if (xwAbsoluteBodyLayout.toData() != null) { |
||||
xwAbsoluteBodyLayout.toData().setBorderStyleFollowingTheme(wAbsoluteBodyLayout.isBorderStyleFollowingTheme()); |
||||
xwAbsoluteBodyLayout.toData().setBorderStyle(wAbsoluteBodyLayout.getBorderStyle()); |
||||
} |
||||
xwAbsoluteBodyLayout.refreshStylePreviewEffect(); |
||||
if (xWFitLayout.toData() != null) { |
||||
xWFitLayout.toData().resetStyle(); |
||||
} |
||||
xWFitLayout.refreshStylePreviewEffect(); |
||||
formDesigner.switchBodyLayout(xwAbsoluteBodyLayout); |
||||
} catch (Exception e) { |
||||
FineLoggerFactory.getLogger().error(e.getMessage(), e); |
||||
|
||||
} |
||||
} |
||||
|
||||
private Rectangle[] getBackupBoundsFromFitLayout(XWFitLayout xWFitLayout) { |
||||
int count = xWFitLayout.getComponentCount(); |
||||
Rectangle[] rectangles = new Rectangle[count]; |
||||
for (int i = 0; i < count; i++) { |
||||
rectangles[i] = xWFitLayout.getComponent(i).getBounds(); |
||||
} |
||||
return rectangles; |
||||
} |
||||
|
||||
protected void copyLayoutAttr(WSortLayout srcLayout, WSortLayout destLayout) { |
||||
destLayout.clearListeners(); |
||||
destLayout.clearMobileWidgetList(); |
||||
for (int i = 0, len = srcLayout.getMobileWidgetListSize(); i < len; i++) { |
||||
destLayout.addMobileWidget(srcLayout.getMobileWidget(i)); |
||||
} |
||||
destLayout.setSorted(true); |
||||
for (int i = 0, len = srcLayout.getListenerSize(); i < len; i++) { |
||||
destLayout.addListener(srcLayout.getListener(i)); |
||||
} |
||||
srcLayout.clearListeners(); |
||||
srcLayout.clearMobileWidgetList(); |
||||
} |
||||
|
||||
|
||||
private void switchLayoutFromAbsolute2Fit(XWFitLayout xwFitLayout) { |
||||
XWAbsoluteBodyLayout xwAbsoluteBodyLayout = getAbsoluteBodyLayout(xwFitLayout); |
||||
if (xwAbsoluteBodyLayout == null) { |
||||
return; |
||||
} |
||||
WAbsoluteBodyLayout layout = xwAbsoluteBodyLayout.toData(); |
||||
WFitLayout wFitLayout = xwFitLayout.toData(); |
||||
wFitLayout.resetStyle(); |
||||
xwFitLayout.switch2FitBodyLayout(xwAbsoluteBodyLayout); |
||||
// 切换布局类型时,保留body背景样式
|
||||
if (wFitLayout != null) { |
||||
wFitLayout.setBorderStyleFollowingTheme(layout.isBorderStyleFollowingTheme()); |
||||
wFitLayout.setBorderStyle(layout.getBorderStyle()); |
||||
} |
||||
copyLayoutAttr(layout, xwFitLayout.toData()); |
||||
|
||||
copyLayoutAttr(layout, xwFitLayout.toData()); |
||||
xwFitLayout.refreshStylePreviewEffect(); |
||||
} |
||||
|
||||
private XWAbsoluteBodyLayout getAbsoluteBodyLayout(XWFitLayout xwFitLayout) { |
||||
if (xwFitLayout != null && xwFitLayout.getComponentCount() > 0) { |
||||
Component component = xwFitLayout.getComponent(0); |
||||
if (component instanceof XWAbsoluteBodyLayout) { |
||||
return (XWAbsoluteBodyLayout) component; |
||||
} |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
private JPanel createAreaScalePane() { |
||||
initLayoutComboBox(); |
||||
|
||||
UILabel layoutTypeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_Attr_Layout_Type")); |
||||
UILabel scaleModeLabel = FRWidgetFactory.createLineWrapLabel(com.fr.design.i18n.Toolkit.i18nText("Fine-Design_Form_PC_Fit_Config_Scale_Setting")); |
||||
Component[][] components = new Component[][]{ |
||||
{layoutTypeLabel, layoutComboBox}, |
||||
{scaleModeLabel, scaleComboBox} |
||||
}; |
||||
JPanel contentPane = TableLayoutHelper.createGapTableLayoutPane(components, |
||||
TableLayoutHelper.FILL_LASTCOLUMN, 20, IntervalConstants.INTERVAL_L1); |
||||
JPanel containerPane = FRGUIPaneFactory.createBorderLayout_S_Pane(); |
||||
containerPane.add(contentPane, BorderLayout.CENTER); |
||||
|
||||
return containerPane; |
||||
} |
||||
|
||||
|
||||
public void initLayoutComboBox() { |
||||
Item[] items = FRLayoutTypeItems.ITEMS; |
||||
DefaultComboBoxModel model = new DefaultComboBoxModel(); |
||||
for (Item item : items) { |
||||
model.addElement(item); |
||||
} |
||||
scaleComboBox = new UIComboBox(model); |
||||
scaleComboBox.setModel(new DefaultComboBoxModel(fitAttrModelType.getFitLayoutScaleAttr())); |
||||
layoutComboBox = new UIComboBox(model); |
||||
layoutComboBox.setPreferredSize(new Dimension(160, 20)); |
||||
scaleComboBox.setPreferredSize(new Dimension(160, 20)); |
||||
WFitLayout wFitLayout = jForm.getTarget().getWFitLayout(); |
||||
layoutComboBox.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
int selectIndex = layoutComboBox.getSelectedIndex(); |
||||
if (selectIndex == 0) { |
||||
if (wFitLayout.getBodyLayoutType() == WBodyLayoutType.ABSOLUTE) { |
||||
int selVal = FineJOptionPane.showConfirmDialog( |
||||
FormFitAttrPane.this, |
||||
Toolkit.i18nText("Fine-Design_Form_Layout_Switch_Tip"), |
||||
Toolkit.i18nText("Fine-Design_Basic_Alert"), |
||||
OK_CANCEL_OPTION, |
||||
WARNING_MESSAGE |
||||
); |
||||
if (OK_OPTION != selVal) { |
||||
layoutComboBox.setSelectedIndex(1); |
||||
return; |
||||
} |
||||
} |
||||
scaleComboBox.setModel(new DefaultComboBoxModel(fitAttrModelType.getFitLayoutScaleAttr())); |
||||
} else { |
||||
scaleComboBox.setModel(new DefaultComboBoxModel(fitAttrModelType.getAbsoluteLayoutSaleAttr())); |
||||
} |
||||
scaleComboBox.setSelectedIndex(0); |
||||
} |
||||
}); |
||||
|
||||
scaleComboBox.addActionListener(new ActionListener() { |
||||
@Override |
||||
public void actionPerformed(ActionEvent e) { |
||||
WBodyLayoutType selectBodyType = WBodyLayoutType.parse(layoutComboBox.getSelectedIndex()); |
||||
int state = fitAttrModelType.parseScaleAttrFromShowIndex(scaleComboBox.getSelectedIndex(), selectBodyType); |
||||
fitConfigPane.refreshPreviewJPanel(FitType.parseByFitState(state)); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
|
||||
@Override |
||||
public void populateBean(ReportFitAttr reportFitAttr) { |
||||
WFitLayout wFitLayout = jForm.getTarget().getWFitLayout(); |
||||
layoutComboBox.setSelectedIndex(wFitLayout.getBodyLayoutType().getTypeValue()); |
||||
scaleComboBox.setSelectedIndex(fitAttrModelType.getScaleAttrShowIndex(wFitLayout)); |
||||
|
||||
if (reportFitAttr == null) { |
||||
itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_Using_Server_Report_View_Settings")); |
||||
} else { |
||||
itemChoose.setSelectedItem(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single")); |
||||
} |
||||
if (reportFitAttr == null) { |
||||
reportFitAttr = fitAttrModelType.getFitAttrModel().getGlobalReportFitAttr(); |
||||
} |
||||
setEnabled(isTemplateSingleSet()); |
||||
fitConfigPane.populateBean(reportFitAttr); |
||||
} |
||||
|
||||
private boolean isTemplateSingleSet() { |
||||
return ComparatorUtils.equals(Toolkit.i18nText("Fine-Design_Report_I_Want_To_Set_Single"), itemChoose.getSelectedItem()); |
||||
} |
||||
|
||||
|
||||
public void setEnabled(boolean enabled) { |
||||
super.setEnabled(enabled); |
||||
fitConfigPane.setEnabled(enabled); |
||||
} |
||||
|
||||
@Override |
||||
protected String title4PopupWindow() { |
||||
return i18nText("Fine-Designer_PC_Fit_Attr"); |
||||
} |
||||
|
||||
} |
@ -1,33 +0,0 @@
|
||||
package com.fr.design.mainframe; |
||||
|
||||
import com.fr.design.designer.beans.models.AddingModel; |
||||
import com.fr.design.file.HistoryTemplateListPane; |
||||
|
||||
import javax.swing.JComponent; |
||||
import javax.swing.TransferHandler; |
||||
import java.awt.datatransfer.Transferable; |
||||
|
||||
public class DesignerTransferHandler extends TransferHandler { |
||||
|
||||
private FormDesigner designer; |
||||
private AddingModel addingModel; |
||||
|
||||
public DesignerTransferHandler(FormDesigner designer, AddingModel addingModel) { |
||||
super("rootComponent"); |
||||
this.designer = designer; |
||||
this.addingModel = addingModel; |
||||
} |
||||
|
||||
protected void exportDone(JComponent source, Transferable data, int action) { |
||||
if (!addingModel.isCreatorAdded()) { |
||||
undoWhenAddingFailed(); |
||||
} |
||||
} |
||||
|
||||
private void undoWhenAddingFailed() { |
||||
JTemplate<?, ?> jt = HistoryTemplateListPane.getInstance().getCurrentEditingTemplate(); |
||||
if (jt != null) { |
||||
jt.undoToCurrent(); |
||||
} |
||||
} |
||||
} |
@ -1,210 +0,0 @@
|
||||
package com.fr.design.designer.beans.models; |
||||
|
||||
import com.fr.base.chart.BaseChartCollection; |
||||
import com.fr.config.dao.DaoContext; |
||||
import com.fr.config.dao.impl.LocalClassHelperDao; |
||||
import com.fr.config.dao.impl.LocalEntityDao; |
||||
import com.fr.config.dao.impl.LocalXmlEntityDao; |
||||
import com.fr.design.designer.creator.CRPropertyDescriptor; |
||||
import com.fr.design.designer.creator.XChartEditor; |
||||
import com.fr.design.designer.creator.XCreator; |
||||
import com.fr.design.designer.creator.XLayoutContainer; |
||||
import com.fr.design.designer.creator.XWTitleLayout; |
||||
import com.fr.design.designer.creator.cardlayout.XWCardLayout; |
||||
import com.fr.design.gui.chart.MiddleChartComponent; |
||||
import com.fr.design.mainframe.FormDesigner; |
||||
import com.fr.design.module.DesignModuleFactory; |
||||
import com.fr.form.main.Form; |
||||
import com.fr.form.ui.ChartEditor; |
||||
import com.fr.form.ui.Widget; |
||||
import com.fr.form.ui.container.WAbsoluteLayout; |
||||
import com.fr.form.ui.container.WCardLayout; |
||||
import com.fr.form.ui.container.WTitleLayout; |
||||
import com.fr.stable.core.PropertyChangeListener; |
||||
import org.easymock.EasyMock; |
||||
import org.junit.After; |
||||
import org.junit.Assert; |
||||
import org.junit.Before; |
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.powermock.api.easymock.PowerMock; |
||||
import org.powermock.core.classloader.annotations.PowerMockIgnore; |
||||
import org.powermock.core.classloader.annotations.PrepareForTest; |
||||
import org.powermock.modules.junit4.PowerMockRunner; |
||||
|
||||
import javax.swing.JComponent; |
||||
import java.awt.Dimension; |
||||
import java.awt.Rectangle; |
||||
import java.beans.IntrospectionException; |
||||
|
||||
@PrepareForTest({DesignModuleFactory.class}) |
||||
@PowerMockIgnore({"com.sun.*", "javax.*", "com.fr.jvm.assist.*"}) |
||||
@RunWith(PowerMockRunner.class) |
||||
public class AddingModelTest { |
||||
|
||||
@Before |
||||
public void setUp() { |
||||
DaoContext.setXmlEntityDao(new LocalXmlEntityDao()); |
||||
DaoContext.setClassHelperDao(new LocalClassHelperDao()); |
||||
DaoContext.setEntityDao(new LocalEntityDao()); |
||||
} |
||||
|
||||
@After |
||||
public void tearDown() { |
||||
DaoContext.setXmlEntityDao(null); |
||||
DaoContext.setClassHelperDao(null); |
||||
DaoContext.setEntityDao(null); |
||||
} |
||||
|
||||
/** |
||||
* 默认名字 + i |
||||
*/ |
||||
@Test |
||||
public void testInstantiateCreator() throws Exception { |
||||
|
||||
Dimension dimension = new Dimension(20, 20); |
||||
|
||||
ChartEditor chartEditor1 = new ChartEditor(); |
||||
XCreator xCreator1 = new DemoCreator(chartEditor1, dimension, "test"); |
||||
|
||||
ChartEditor chartEditor2 = new ChartEditor(); |
||||
chartEditor2.setWidgetName("test02"); |
||||
XCreator xCreator2 = new DemoCreator(chartEditor2, dimension, "test02"); |
||||
xCreator1.add(xCreator2); |
||||
|
||||
ChartEditor chartEditor3 = new ChartEditor(); |
||||
chartEditor3.setWidgetName("test03"); |
||||
WAbsoluteLayout.BoundsWidget boundsWidget = new WAbsoluteLayout.BoundsWidget(chartEditor3, new Rectangle(dimension)); |
||||
WTitleLayout wTitleLayout03 = new WTitleLayout(); |
||||
wTitleLayout03.addWidget(boundsWidget); |
||||
//需要和内部的 widget 一样
|
||||
wTitleLayout03.setWidgetName("test03"); |
||||
XWTitleLayout xCreator3 = new XWTitleLayout(wTitleLayout03, dimension); |
||||
xCreator1.add(xCreator3); |
||||
|
||||
AddingModel addingModel = new AddingModel(xCreator1, 20, 20); |
||||
|
||||
Form form = EasyMock.mock(Form.class); |
||||
EasyMock.expect(form.isNameExist("test0")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist("test03")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); |
||||
EasyMock.replay(form); |
||||
|
||||
FormDesigner mock = EasyMock.mock(FormDesigner.class); |
||||
EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); |
||||
EasyMock.replay(mock); |
||||
|
||||
addingModel.instantiateCreator(mock); |
||||
//没有默认参数, 但已经存在 test
|
||||
Assert.assertEquals("test1", xCreator1.toData().getWidgetName()); |
||||
//直接返回
|
||||
Assert.assertEquals("test020", xCreator2.toData().getWidgetName()); |
||||
//已经存在,后接0
|
||||
Assert.assertEquals("test030", xCreator3.toData().getWidgetName()); |
||||
} |
||||
|
||||
@Test |
||||
public void testInstantiateCreator_cardLayout() throws Exception { |
||||
|
||||
Form form = EasyMock.mock(Form.class); |
||||
EasyMock.expect(form.isNameExist("cardlayout0")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist("cardlayout1")).andReturn(true).once(); |
||||
EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); |
||||
EasyMock.replay(form); |
||||
|
||||
FormDesigner mock = EasyMock.mock(FormDesigner.class); |
||||
EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); |
||||
EasyMock.replay(mock); |
||||
|
||||
WCardLayout wCardLayout = new WCardLayout(20, 20); |
||||
XWCardLayout xwCardLayout = new XWCardLayout(wCardLayout, new Dimension(40, 40)); |
||||
AddingModel addingModel = new AddingModel(mock, xwCardLayout); |
||||
Assert.assertEquals("cardlayout2", xwCardLayout.toData().getWidgetName()); |
||||
|
||||
//依赖于 cardlayout 创建 container
|
||||
XLayoutContainer parentLayOut = xwCardLayout.initCreatorWrapper(80); |
||||
//组件默认名 tablelayout2
|
||||
AddingModel parentModel = new AddingModel(mock, parentLayOut); |
||||
//经过处理 tablayout20
|
||||
Assert.assertEquals("tablayout20", parentLayOut.toData().getWidgetName()); |
||||
Assert.assertEquals("tabpane20", ((XCreator) (parentLayOut.getComponent(0))).getXCreator().toData().getWidgetName()); |
||||
Assert.assertEquals("cardlayout20", xwCardLayout.toData().getWidgetName()); |
||||
|
||||
} |
||||
|
||||
@Test |
||||
public void testInstantiateCreator_containsNotXCreator() throws Exception { |
||||
|
||||
Form form = EasyMock.mock(Form.class); |
||||
EasyMock.expect(form.isNameExist(EasyMock.anyString())).andReturn(false).anyTimes(); |
||||
EasyMock.replay(form); |
||||
|
||||
FormDesigner mock = EasyMock.mock(FormDesigner.class); |
||||
EasyMock.expect(mock.getTarget()).andReturn(form).anyTimes(); |
||||
EasyMock.replay(mock); |
||||
|
||||
PowerMock.mockStaticPartial(DesignModuleFactory.class, "getChartComponent"); |
||||
EasyMock.expect(DesignModuleFactory.getChartComponent(EasyMock.anyObject(BaseChartCollection.class))).andReturn(new MiddleChartComponent() { |
||||
@Override |
||||
public void populate(BaseChartCollection cc) { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public BaseChartCollection update() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
public void reset() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public void addStopEditingListener(PropertyChangeListener list) { |
||||
|
||||
} |
||||
}).anyTimes(); |
||||
PowerMock.replayAll(); |
||||
|
||||
Dimension dimension = new Dimension(20, 20); |
||||
|
||||
ChartEditor chartEditor1 = new ChartEditor(); |
||||
XCreator xCreator1 = new XChartEditor(chartEditor1, dimension); |
||||
|
||||
|
||||
AddingModel chartModel = new AddingModel(mock, xCreator1); |
||||
Assert.assertEquals("chart0", xCreator1.toData().getWidgetName()); |
||||
} |
||||
|
||||
private static class DemoCreator extends XCreator { |
||||
|
||||
private String widgetName; |
||||
|
||||
public DemoCreator(Widget ob, Dimension initSize, String defaultName) { |
||||
super(ob, initSize); |
||||
this.widgetName = defaultName; |
||||
} |
||||
|
||||
@Override |
||||
public CRPropertyDescriptor[] supportedDescriptor() throws IntrospectionException { |
||||
return new CRPropertyDescriptor[0]; |
||||
} |
||||
|
||||
@Override |
||||
protected JComponent initEditor() { |
||||
return null; |
||||
} |
||||
|
||||
@Override |
||||
protected void initXCreatorProperties() { |
||||
|
||||
} |
||||
|
||||
@Override |
||||
public String createDefaultName() { |
||||
return this.widgetName; |
||||
} |
||||
} |
||||
|
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue